|
1 | 1 | #' Mocking tools |
2 | 2 | #' |
3 | 3 | #' @description |
4 | | -#' `r lifecycle::badge("experimental")` |
5 | | -#' |
6 | 4 | #' `with_mocked_bindings()` and `local_mocked_bindings()` provide tools for |
7 | 5 | #' "mocking", temporarily redefining a function so that it behaves differently |
8 | 6 | #' during tests. This is helpful for testing functions that depend on external |
|
48 | 46 | #' |
49 | 47 | #' ## Base functions |
50 | 48 | #' |
51 | | -#' Note that it's not possible to mock functions in the base namespace |
52 | | -#' (i.e. functions that you can use without explicitly importing them) |
53 | | -#' since currently we don't know of a way to to mock them without potentially |
54 | | -#' affecting all running code. If you need to mock a base function, you'll |
55 | | -#' need to create a wrapper, as described below. |
| 49 | +#' To mock a function in the base package, you need to make sure that you |
| 50 | +#' have a binding for this function in your package. It's easiest to do this |
| 51 | +#' by binding the value to `NULL`. For example, if you wanted to mock |
| 52 | +#' `interactive()` in your package, you'd need to include this code somewhere |
| 53 | +#' in your package: |
| 54 | +#' |
| 55 | +#' ```R |
| 56 | +#' interactive <- NULL |
| 57 | +#' ``` |
| 58 | +#' |
| 59 | +#' Why is this necessary? `with_mocked_bindings()` and `local_mocked_bindings()` |
| 60 | +#' work by temporarily modifying the bindings within your package's namespace. |
| 61 | +#' When these tests are running inside of `R CMD check` the namespace is locked |
| 62 | +#' which means it's not possible to create new bindings so you need to make sure |
| 63 | +#' that the binding exists already. |
56 | 64 | #' |
57 | 65 | #' ## Namespaced calls |
58 | 66 | #' |
|
65 | 73 | #' } |
66 | 74 | #' ``` |
67 | 75 | #' |
68 | | -#' To mock here, you'll need to modify `another_function()` inside the |
| 76 | +#' To mock this function, you'd need to modify `another_function()` inside the |
69 | 77 | #' `anotherpackage` package. You _can_ do this by supplying the `.package` |
70 | | -#' argument: |
71 | | -#' |
72 | | -#' ```R |
73 | | -#' local_mocked_bindings( |
74 | | -#' another_function = function(...) "new_value", |
75 | | -#' .package = "anotherpackage" |
76 | | -#' ) |
77 | | -#' ``` |
78 | | -#' |
79 | | -#' But it's not a great idea to mock a namespace that you don't own because |
80 | | -#' it affects all code in that package, not just code in your package. Instead, |
81 | | -#' it's safer to either import the function into your package, or make a wrapper |
82 | | -#' that you can mock: |
| 78 | +#' argument to `local_mocked_bindings()` but we don't recommend it because |
| 79 | +#' it will affect all calls to `anotherpackage::another_function()`, not just |
| 80 | +#' the calls originating in your package. Instead, it's safer to either import |
| 81 | +#' the function into your package, or make a wrapper that you can mock: |
83 | 82 | #' |
84 | 83 | #' ```R |
85 | 84 | #' some_function <- function() { |
|
98 | 97 | #' @param code Code to execute with specified bindings. |
99 | 98 | #' @param .env Environment that defines effect scope. For expert use only. |
100 | 99 | #' @param .package The name of the package where mocked functions should be |
101 | | -#' inserted. Generally, you should not need to supply this as it will be |
102 | | -#' automatically detected when whole package tests are run or when there's |
103 | | -#' one package under active development (i.e. loaded with |
104 | | -#' [pkgload::load_all()]). |
| 100 | +#' inserted. Generally, you should not supply this as it will be automatically |
| 101 | +#' detected when whole package tests are run or when there's one package |
| 102 | +#' under active development (i.e. loaded with [pkgload::load_all()]). |
| 103 | +#' We don't recommend using this to mock functions in other packages, |
| 104 | +#' as you should not modify namespaces that you don't own. |
105 | 105 | local_mocked_bindings <- function(..., .package = NULL, .env = caller_env()) { |
106 | 106 | bindings <- list2(...) |
107 | 107 | check_bindings(bindings) |
@@ -232,6 +232,10 @@ test_mock_method.integer <- function(x) { |
232 | 232 | "y" |
233 | 233 | } |
234 | 234 |
|
| 235 | +test_mock_base <- function() { |
| 236 | + interactive() |
| 237 | +} |
| 238 | +interactive <- NULL |
235 | 239 |
|
236 | 240 | show_bindings <- function(name, env = caller_env()) { |
237 | 241 | envs <- env_parents(env) |
|
0 commit comments