Testthat: with_mock not working when inside test_that function

Created on 23 Mar 2018  路  7Comments  路  Source: r-lib/testthat

I can't get the with_mock example to work when it is inside a test_that.
I tested it in a fresh R session (R version 3.4.3, testthat version 2.0.0)

> library(testthat)
> test_that("lalal", {
+ add_one <- function(x) x + 1
+ expect_equal(add_one(2), 3)
+ with_mock(
+   add_one = function(x) x - 1,
+   expect_equal(add_one(2), 1)
+ )
+ square_add_one <- function(x) add_one(x) ^ 2
+ expect_equal(square_add_one(2), 9)
+ expect_equal(
+   with_mock(
+     add_one = function(x) x - 1,
+     square_add_one(2)
+   ),
+   1
+ )})
Fehler: Test failed: 'lalal'
* Function add_one not found in environment testthat.
1: with_mock(add_one = function(x) x - 1, expect_equal(add_one(2), 1)) at :4
2: extract_mocks(new_values = new_values[!code_pos], .env = .env, eval_env = parent.frame())
3: lapply(stats::setNames(nm = mock_qual_names), function(qual_name) {
       pkg_name <- gsub(pkg_and_name_rx, "\\1", qual_name)
       if (is_base_pkg(pkg_name)) {
           stop("Can't mock functions in base packages (", pkg_name, ")", call. = FALSE)
       }
       name <- gsub(pkg_and_name_rx, "\\2", qual_name)
       if (pkg_name == "")
           pkg_name <- .env
       env <- asNamespace(pkg_name)
       if (!exists(name, envir = env, mode = "function"))
           stop("Function ", name, " not found in environment ", environmentName(env),
               ".", call. = FALSE)
       mock(name = name, env = env, new = eval(new_values[[qual_name]], eval_env, eval_env))
   })
4: FUN(X[[i]], ...)
5: stop("Function ", name, " not f
> add_one <- function(x) x + 1
> expect_equal(add_one(2), 3)
> with_mock(
+   add_one = function(x) x - 1,
+   expect_equal(add_one(2), 1)
+ )
> square_add_one <- function(x) add_one(x) ^ 2
> expect_equal(square_add_one(2), 9)
> expect_equal(
+   with_mock(
+     add_one = function(x) x - 1,
+     square_add_one(2)
+   ),
+   1
+ )
> test_that("doing",{
+ add_one <- function(x) x + 1
+ expect_equal(add_one(2), 3)
+ with_mock(
+   add_one = function(x) x - 1,
+   expect_equal(add_one(2), 1)
+ )
+ square_add_one <- function(x) add_one(x) ^ 2
+ expect_equal(square_add_one(2), 9)
+ expect_equal(
+   with_mock(
+     add_one = function(x) x - 1,
+     square_add_one(2)
+   ),
+   1
+ )})
Fehler: Test failed: 'doing'
* add_one(2) not equal to 1.
1/1 mismatches
[1] 3 - 1 == 2
* with_mock(add_one = function(x) x - 1, square_add_one(2)) not equal to 1.
1/1 mismatches
[1] 9 - 1 == 8
>

If someone could help me on that, it would be great.

Most helpful comment

It should work if you fully qualify the function name (include the pkgname).

e.g.

with_mock(
  "pkgname:::add_one" = function()

All 7 comments

Does it work if you put add_one outside the test_that call?

actually, if I run in the console:

  add_one <- function(x) x + 1
 test_that("lala", {

   expect_equal(add_one(2), 3)
   f <- function() {}
   with_mock(
     add_one = function(x) x - 1,
     expect_equal(add_one(2), 1)
   )
 })

it works.
But if i run it via devtools::test() it fails (version: devtools_1.13.5)

This is an expected behaviour.

Test that is trying to find function inside the package if test_package() is called:

env <- asNamespace(pkg_name)
if (!exists(name, envir = env, mode = "function")) 
  stop("Function ", name, " not found in environment ", 
               environmentName(env), ".", call. = FALSE)

If you want to test functions outside the package , you might try calling test_dir.

So now I have the function I want to mock inside the R folder of my package. When only I execute the expect_that & with_mock piece of code, the mocking works fine. However if I have the same code that I execute through devtools::test() it doesn't mock it and use the original implementation.
What I am doing wrong?

@hannaET I cannot reproduce that using your code.

I have tried it with:

  • devtools 1.12.x and 1.13.5
  • testthat 2.0.0

It should work if you fully qualify the function name (include the pkgname).

e.g.

with_mock(
  "pkgname:::add_one" = function()

I suggest to add a note to the documentation for the requirement to fully qualify the function when used with devtools::test(). Should I make a PR for this?

Was this page helpful?
0 / 5 - 0 ratings