How can I make testthat think I don't have a package installed?

I'm using testthat to write unit tests for a package. In one part of my package, I include a check to make sure a different package is installed:

  if (!requireNamespace("otherpackage", quietly = TRUE)) {
    stop("Package \"otherpackage\" isn't installed", call. = FALSE)
  }

I'm trying to write a test that will cover that stop() call, but can't ever get there because "otherpackage" is installed on my computer.

The closest idea I've found is using withr::libpaths() to create a temporary empty library, but I can't get it to actually work. For instance, if I run:

withr::with_temp_libpaths({
  installed.packages()
})

…I still get a list of all the packages installed on my computer, not an empty environment.

Is there a way to make testthat think that I don't have the package installed?

3 Likes

I'd use mocking with testthat::with_mock(). I'm not sure of two things: whether you want/need to use a further package to mock a base R function (not possible with testthat nowadays) and how to mock the results for a function call with arguments so maybe something like

In the actual package code:

is_otherpackage_installed <- function(){
  requireNamespace("otherpackage", quietly = TRUE)
}
if (!is_otherpackage_installed()) {
    stop("Package \"otherpackage\" isn't installed", call. = FALSE)
  }

then in the test

test_that("otherpackage installation is checked", {
  with_mock(
  is_other_package_installed = function() FALSE,
  expect_error(blabla, 'Package \"otherpackage\"')
)
})

Note that with_mock() isn't documented in testthat's pkgdown website so maybe one is supposed to use mockery or mockr for mocking? :thinking:

7 Likes

I found a relevant SO thread.

5 Likes

Whoa, this is so cool!

The only thing I had to change was fully qualifying the package name in with_mock():

with_mock("mypackage::is_other_package_installed" = function() FALSE, ...)

Without that, devtools::test() worked just fine in RStudio when typing ⌘⇧T, but it failed with covr::report() or R CMD CHECK.

6 Likes

I used to have a similar problem - I was testing for a condition that was certain to be met on my computer or Travis.

At the end I resolved it by including an OR to a logical environment variable in the if() call - and then set it as necessary in my test case. So while the actual condition being tested does not actually happen (in my case no computer is truly offline) the OR triggers the condition and executes the stop / warning call.

network <- as.logical(Sys.getenv("NETWORK_UP", unset = TRUE)) # dummy variable to allow testing of network


if (httr::http_error(remote_file) | !network) {

      message('No internet connection or data source broken.')
      return(NULL)

}

and in my tests

Sys.setenv("NETWORK_UP" = FALSE)
expect_message(okresy(), "internet") # message, not warning - as per CRAN policy...
Sys.setenv("NETWORK_UP" = TRUE)
2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.