I have a function like this:
func <- function(x) {
if (requireNamespace("broom", quietly = TRUE)) {
print(1)
} else {
print(2)
}
I'd like to write tests using testthat
that trigger both cases. But of course broom
either is or isn't installed on my computer. What to do?
Edit: this no longer works as of testthat-2.0.0
. According to a change in Oct 2017:
Rest of the answer only applies to older versions of testthat
.
testthat::with_mock
should do what you want.
library(testthat)
somefunc <- function() if (requireNamespace("base", quietly=TRUE)) 1L else 2L
Some simple tests:
expect_equal( somefunc(), 1L )
Successful.
expect_equal( somefunc(), 2L )
# Error: somefunc() not equal to 2.
# 1/1 mismatches
# [1] 1 - 2 == -1
Expected.
Let's create a "mock" function that overrides the base function:
with_mock(
`base::requireNamespace` = function(package, ..., quietly=FALSE) FALSE,
expect_equal( somefunc(), 1L )
)
# Error: somefunc() not equal to 1.
# 1/1 mismatches
# [1] 2 - 1 == 1
with_mock(
`base::requireNamespace` = function(package, ..., quietly=FALSE) FALSE,
expect_equal( somefunc(), 2L )
)
# [1] 2
Note: on success, expect_equal
invisibly returns the return value, so you don't see [1] 1
in the first example. with_mock
, on success, returns the return value but not invisibly. In both cases, failure will return a modified return value. This minute difference should not affect any tests.
Depending on the function you are overriding, it makes sense (to me) to be careful to define the mock function with identical formals. You might be able to shortcut this if you know exactly how it is always called in all subordinate functions during your tests, but I think the extra careful attention to the formals will preclude really hard-to-troubleshoot test failures.
NB: the help states that this
... is still experimental, so use with care.