如何从基础模拟函数?
How to mock functions from base?
我在我的代码中从 base 调用一个函数,我想在我的 testthat
单元测试中模拟这个函数。
我该怎么做?
library(testthat)
my.func <- function() {
return(Sys.info()["sysname"]) # e. g. "Linux"
}
my.func()
# sysname
# "Linux"
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(list(sysname = "Clever OS")), # see edit 2 !!!
expect_equal(my.func(), "Clever OS", fixed = TRUE)
)
)
# Error: Test failed: 'base function can be mocked'
# * my.func() not equal to "Clever OS".
?with_mock
说:
Functions in base packages cannot be mocked, but this can be worked
around easily by defining a wrapper function.
我可以通过我从 my.func
调用的包装函数来封装对 Sys.info()
的基本函数调用,但假设我不能这样做,因为我正在测试一个包中的函数,我不能改变...
有什么解决办法吗?
我在 Ubuntu 14.04 上使用 R3.4.4 64 位和 testthat 2.0.0.9000。
编辑 1:
使用
`base::Sys.info` = function() return(list(sysname = "Clever OS"))
导致 testthat
错误消息:
Can't mock functions in base packages (base)
编辑 2: 正如@suren 在他的回答中显示我的代码示例是错误的(模拟函数 returns 另一个 class 然后是原始函数:-(
正确的 mock 函数应该是:Sys.info = function() return(c(sysname = "Clever OS"))
错误信息是my.func()不等于"Clever OS".。
原因是 Sys.info
returns 一个命名的字符向量,而你的模拟函数是 list
.
只需修改模拟函数和期望值即可:
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(c(sysname = "Clever OS")),
expect_equal(my.func(), c(sysname = "Clever OS"), fixed = TRUE)
)
)
这甚至在一个包中也有效。
注意:根据 with_mock
的帮助,基函数的模拟不应该起作用,但它确实起作用(至少目前)。
以下 (my.func()$`sysname`) 似乎通过了问题中的原始代码的测试。
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(list(sysname = "Clever OS")),
expect_equal(my.func()$`sysname`, "Clever OS", fixed = TRUE)
)
)
或者,有一个列表,其中 expect_equal
中的字符串
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(list(sysname = "Clever OS")),
expect_equal(my.func(), list(`sysname` = "Clever OS"), fixed = TRUE)
)
)
关于使用 with_mock
模拟基函数的警告:
即使在我的问题和@Suren 接受的答案的情况下,基函数的模拟可能会起作用,包 testthat
中围绕 with_mock
的许多问题不鼓励模拟基包函数(甚至在被测包之外的功能),e。 g.
testthat 2.0.0 - Breaking API changes
- "Can't mock functions in base packages":您不能再使用 with_mock() 来模拟基础包中的函数,因为由于字节码编译器的变化,这在 R-devel 中不再有效。 我建议改用
mockery
或 mockr
。
Don't allow base packages to be mocked
with_mock() function seems to interact badly with the JIT compiler
- 正如我在 hadley/testthat#546(评论)中提到的,mockery 已经有一个替代函数 with_mock 称为存根,它采用不同的方法来模拟事物不受其他线程中提出的问题的限制。如果 with_mock 坏了,我认为这个包在 mockery 上也能正常工作。我还认为 mockery 是放置 with_mock 的合理位置,出于遗留原因,它可以与 stub 并存。
我在我的代码中从 base 调用一个函数,我想在我的 testthat
单元测试中模拟这个函数。
我该怎么做?
library(testthat)
my.func <- function() {
return(Sys.info()["sysname"]) # e. g. "Linux"
}
my.func()
# sysname
# "Linux"
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(list(sysname = "Clever OS")), # see edit 2 !!!
expect_equal(my.func(), "Clever OS", fixed = TRUE)
)
)
# Error: Test failed: 'base function can be mocked'
# * my.func() not equal to "Clever OS".
?with_mock
说:
Functions in base packages cannot be mocked, but this can be worked around easily by defining a wrapper function.
我可以通过我从 my.func
调用的包装函数来封装对 Sys.info()
的基本函数调用,但假设我不能这样做,因为我正在测试一个包中的函数,我不能改变...
有什么解决办法吗?
我在 Ubuntu 14.04 上使用 R3.4.4 64 位和 testthat 2.0.0.9000。
编辑 1:
使用
`base::Sys.info` = function() return(list(sysname = "Clever OS"))
导致 testthat
错误消息:
Can't mock functions in base packages (base)
编辑 2: 正如@suren 在他的回答中显示我的代码示例是错误的(模拟函数 returns 另一个 class 然后是原始函数:-(
正确的 mock 函数应该是:Sys.info = function() return(c(sysname = "Clever OS"))
错误信息是my.func()不等于"Clever OS".。
原因是 Sys.info
returns 一个命名的字符向量,而你的模拟函数是 list
.
只需修改模拟函数和期望值即可:
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(c(sysname = "Clever OS")),
expect_equal(my.func(), c(sysname = "Clever OS"), fixed = TRUE)
)
)
这甚至在一个包中也有效。
注意:根据 with_mock
的帮助,基函数的模拟不应该起作用,但它确实起作用(至少目前)。
以下 (my.func()$`sysname`) 似乎通过了问题中的原始代码的测试。
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(list(sysname = "Clever OS")),
expect_equal(my.func()$`sysname`, "Clever OS", fixed = TRUE)
)
)
或者,有一个列表,其中 expect_equal
test_that("base function can be mocked",
with_mock(
Sys.info = function() return(list(sysname = "Clever OS")),
expect_equal(my.func(), list(`sysname` = "Clever OS"), fixed = TRUE)
)
)
关于使用 with_mock
模拟基函数的警告:
即使在我的问题和@Suren 接受的答案的情况下,基函数的模拟可能会起作用,包 testthat
中围绕 with_mock
的许多问题不鼓励模拟基包函数(甚至在被测包之外的功能),e。 g.
testthat 2.0.0 - Breaking API changes
- "Can't mock functions in base packages":您不能再使用 with_mock() 来模拟基础包中的函数,因为由于字节码编译器的变化,这在 R-devel 中不再有效。 我建议改用
mockery
或mockr
。
Don't allow base packages to be mocked
with_mock() function seems to interact badly with the JIT compiler
- 正如我在 hadley/testthat#546(评论)中提到的,mockery 已经有一个替代函数 with_mock 称为存根,它采用不同的方法来模拟事物不受其他线程中提出的问题的限制。如果 with_mock 坏了,我认为这个包在 mockery 上也能正常工作。我还认为 mockery 是放置 with_mock 的合理位置,出于遗留原因,它可以与 stub 并存。