3
votes

Racket has some neat testing libraries, including Rackunit and Mock. I was wondering whether there's a standard way to monkey-patch internal calls in the function being tested (e.g. similar to python's mock.patch), either using these or other libraries.

That is, suppose we're testing this function:

(define (compute x)
  (+ 1 (consult-api x))

We want to check that compute yields the expected results with different return values of consult-api, which we could validate using Rackunit checks. We'd like to replace consult-api with a mock for the purposes of the test.

The mock library suggests adding keyword arguments to the function being tested so that we can supply such mocks to it for use during testing, but I was hoping for a way that would not involve modifying the original function.

It seems like what we are looking for here could be accomplished with some kind of macro, by rewriting instances of consult-api as mock-consult-api, the latter of which would be a mock defined in the test. I'm not familiar enough with Racket macros to know whether it's possible to define such a macro in a test and have it apply to the compilation of the module being tested.

How should one accomplish this in the best/Rackety-est way?

1

1 Answers

0
votes

You can definitely do this using a macro. It's going to be way way easier if you allow yourself to add a line or two to the top of the file. I claim that one of Racket's design principles is that of strong separate compilation; that is, the meaning of a file depends on the text of the file (and of course on the meanings of the modules that it requires).

You might also look into Units, which were designed to allow flexible runtime linking. To be fair, they haven't gotten a lot of use in the last 20 years.