我目前正在使用软件包testthat
和mockery
进行一些单元测试。我试图理解当使用expect_args
在函数中实际调用模拟函数时,mockery
包中的函数apply
如何工作。以下是测试成功的示例。
myMean <- function(A){
apply(A,1,mean)
}
myMat = matrix(rep(1,6), nrow = 2, ncol = 3)
test_that("myMean calls base::mean correctly",{
m <- mock(1, cycle = TRUE)
with_mock(
`base::mean` = m,
myMean(myMat),
expect_args(m, 1, as.double(myMat[1,])))
})
现在让我们看一个稍微复杂的例子,其中myMean
的参数实际上是data.frame
,需要转换为函数中的矩阵。
myMean <- function(A){
B = as.matrix(A)
apply(B,1,mean)
}
myMat = as.data.frame(myMat)
test_that("myMean calls base::mean correctly",{
m <- mock(1, cycle = TRUE)
with_mock(
`base::mean` = m,
myMean(myMat),
expect_args(m, 1, as.double(myMat[1,])))
})
然后我收到以下错误消息:
Error: Test failed: 'myMeanSimple calls base::mean correct number of times
* 1st actual argument not equal to 1st expected argument.
names for target but not for current
mockery
包的vignette解释了此错误。然而,我无法找到应与as.double(myMat[1,])
关联的参数名称。
答案 0 :(得分:3)
首先,我很高兴这个小实用程序变得有用!其次,您看到的错误源于您的转换执行方式以及expect_args
如何比较结果。在内部,我们调用expect_equal
,要求matrix
的所有名称都在那里。
在调用你的第二个例子后,我运行了这个:
> mock_args(m)
[[1]]
[[1]][[1]]
V1 V2 V3
1 1 1
[[2]]
[[2]][[1]]
V1 V2 V3
1 1 1
因此,您可以看到在第一次调用中传递了一个名为 raw的,并且对于第二次调用也是如此 - 每个列都分配了 names 。这是因为as.matrix
保留了列名。所以这不是关于参数的名称,而是关于数据中被比较的名称。
现在,当您使用expect_args
运行最终比较时,实际上使用的as.double
不保留名称。因此,你看到的错误。要修复它,您只需将期望改为:
expect_args(m, 1, as.matrix(myMat)[1,])
我希望这能解决你的问题。