With version 3.0.0 of
testthat, mocking capabilities provided by
testthat::local_mock() have been deprecated under edition 3. This leaves implementation of function mocking for unit testing to third-party packages, of which two have been published on CRAN:
mockr. While all currently available mocking implementations have their limitations, what sets
mockthat apart from
mockr is coping with S3 dispatch (see example below).
You can install the development version of
mockthat from GitHub with:
# install.packages("devtools") devtools::install_github("nbenn/mockthat")
A release version will be submitted to CRAN shortly.
Mocking in the context of unit testing refers to temporarily replacing a piece of functionality (that might be part of the package being tested or potentially even part of a downstream dependency) in order to cope with limited infrastructure in testing environments (for example absence of a live Internet connection).
jsonlite::fromJSON(), for example, internally calls
curl::curl() when the value passed as
txt argument is a string that resembles an URL. In order to no longer be reliant on an Internet connection, the function
curl::curl() can be substituted with a stub that simply returns a constant.
As mentioned above, the main point of differentiation of
mockthat over the other available packages
mockr is stubbing out functions in the context of S3 dispatch. Assuming the following set-up,
mockthat::with_mock() can be used to catch the call to
foo() and therefore prevent the error from being thrown.
mockthat::with_mock( foo = function(x) "bar", met(x) ) #>  "bar"
This is not possible with the current implementation of
mockr::with_mock( foo = function(x) "bar", met(x) ) #> Error in foo(x): foo
And with the current API of
mockery::stub() it is unclear how the
depth argument should be chosen, as the function
gen() does not contain a call to
met(). Trying a range of sensible values does not yield the desired result.
mockthat also allows for creating mock objects (with class attribute
mock_fun), which allow capture of the call for later examination.
In addition to
mockthat also offers a
local_mock() function, again, mimicking the deprecated
testthat function, which keeps the mocks in place for the life-time of the environment passed as
local_env argument (or if called from the global environment, until
withr::deferred_run() is executed). Mock objects as shown above are created (and returned invisibly) for all non-function objects passed as