diff --git a/NEWS.md b/NEWS.md index 543399049..0b0fd979f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -29,6 +29,8 @@ * `colourise()` was removed. (Colour is still supported, via the `crayon` package.) +* Mocks can now access values local to the call of `with_mock` (#193, @krlmlr). + * All equality expectations are now documented together (#173); all matching expectations are also documented together. diff --git a/R/mock.r b/R/mock.r index 62bffc422..4a890c093 100644 --- a/R/mock.r +++ b/R/mock.r @@ -43,7 +43,7 @@ with_mock <- function(..., .env = topenv()) { } code <- new_values[code_pos] - mocks <- extract_mocks(new_values = new_values[!code_pos], .env = .env) + mocks <- extract_mocks(new_values = new_values[!code_pos], .env = .env, eval_env = parent.frame()) on.exit(lapply(mocks, reset_mock), add = TRUE) lapply(mocks, set_mock) @@ -61,7 +61,7 @@ colons_rx <- "::(?:[:]?)" name_rx <- ".*" pkg_and_name_rx <- sprintf("^(?:(%s)%s)?(%s)$", pkg_rx, colons_rx, name_rx) -extract_mocks <- function(new_values, .env) { +extract_mocks <- function(new_values, .env, eval_env = parent.frame()) { if (is.environment(.env)) .env <- environmentName(.env) mock_qual_names <- names(new_values) @@ -81,7 +81,7 @@ extract_mocks <- function(new_values, .env) { if (!exists(name, envir = env, mode = "function")) stop("Function ", name, " not found in environment ", environmentName(env), ".") - mock(name = name, env = env, new = eval(new_values[[qual_name]])) + mock(name = name, env = env, new = eval(new_values[[qual_name]], eval_env, eval_env)) } ) } diff --git a/tests/testthat/test-mock.r b/tests/testthat/test-mock.r index 163e0d0df..f1fd1cac5 100644 --- a/tests/testthat/test-mock.r +++ b/tests/testthat/test-mock.r @@ -150,3 +150,12 @@ test_that("mock extraction", { expect_identical(extract_mocks(list(acf = identity), "stats")[[1]]$new_value, identity) expect_equal(length(extract_mocks(list(not = identity, `base::!` = identity), "testthat")), 2) }) + +test_that("mocks can access local variables", { + value <- TRUE + + with_mock( + expect_equal(2 * 3, 4), + all.equal = function(x, y, ...) {value} + ) +})