使用模拟与应用R.

时间:2016-12-06 20:45:41

标签: r unit-testing mocking apply

我目前正在使用软件包testthatmockery进行一些单元测试。我试图理解当使用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,])关联的参数名称。

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,])

我希望这能解决你的问题。