R Y*_*oda 12 r mocking testthat
我在我的代码中从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".
Run Code Online (Sandbox Code Playgroud)
?with_mock
说:
无法模拟基础包中的函数,但可以通过定义包装函数轻松解决此问题.
我可以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"))
Run Code Online (Sandbox Code Playgroud)
导致testthat
错误消息:
无法模拟基础包中的函数(基础)
编辑2:由于@suren在他的回答中显示我的代码示例在这里是错误的(模拟函数返回另一个类然后原始的:-(
正确的模拟函数应该是: Sys.info = function() return(c(sysname = "Clever OS"))
错误消息是my.func()不等于"Clever OS"..原因是在模拟Sys.info
函数a时返回命名的字符向量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)
)
)
Run Code Online (Sandbox Code Playgroud)
这甚至可以在包中使用.
注意:基本功能的模拟不应该根据帮助而起作用,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)
)
)
Run Code Online (Sandbox Code Playgroud)
或者,有一个列表中的字符串 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)
)
)
Run Code Online (Sandbox Code Playgroud)