我在我的代码中从 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.
我可以封装对
Sys.info()
的基本函数调用通过我从 my.func
调用的包装函数那么让我们假设我不能这样做,因为我正在测试一个我无法更改的包中的函数......有什么解决办法吗?
我在 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 在他的回答中所显示的,我这里的代码示例是错误的(模拟函数返回另一个类,然后是原始类:-(
正确的模拟函数应该是:
Sys.info = function() return(c(sysname = "Clever OS"))
最佳答案
错误消息是 my.func() 不等于“Clever OS”..
原因是Sys.info
返回一个命名的字符向量,而你的模拟函数是一个 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)
)
)
关于r - 如何从基础模拟函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50438546/