我目前在项目中使用R6类。测试R6中R类中的私有方法R
我想写单元测试,也测试我正在使用的私有方法的功能(最好不要通过使用这些私有方法更复杂的公共方法)。
但是,我无法访问似乎访问私有方法。
我该如何做到最好?
谢谢!
我目前在项目中使用R6类。测试R6中R类中的私有方法R
我想写单元测试,也测试我正在使用的私有方法的功能(最好不要通过使用这些私有方法更复杂的公共方法)。
但是,我无法访问似乎访问私有方法。
我该如何做到最好?
谢谢!
这里不需要环境黑客或改变的解决方案你想要测试的类,而是创建一个新的类来为你做测试。
在R6
,派生类访问类中的方法private
(不像C++
或Java
在您需要的protected
关键字archieve相同的结果)。因此,您可以编写一个从您要测试的类派生的TesterClass
。例如:
library(R6)
ClassToTest <- R6Class(
private = list(
privateMember = 7,
privateFunction = function(x){
return(x * private$privateMember)
}
)
)
TesterClass <- R6Class(
inherit = ClassToTest,
public = list(
runTest = function(x = 5){
if(x * private$privateMember != private$privateFunction(x))
cat("Oops. Somethig is wrong\n")
else
cat("Everything is fine\n")
}
)
)
t <- TesterClass$new()
t$runTest()
# Everything is fine
一个这种方法的优点是,它让你的环境清洁的情况下,要保存详细的测试结果。
目前有一种方法可以访问R6对象的私有环境。但是,由于这是以无证方式进入对象,它可能会在未来破裂......但我认为这很快就不会发生。
# Gets private environment from an R6 object
get_private <- function(x) {
x[['.__enclos_env__']]$private
}
A <- R6::R6Class("A",
private = list(x = 1)
)
a <- A$new()
get_private(a)$x
# [1] 1
您可以添加一个辅助方法get
到类:
...
A <- R6::R6Class(
"A",
private = list(
private_print = function(){print("Ola")}
),
public = list(
get = function(name=NULL){
# recursion
if(length(name)>1){
tmp <- lapply(name, self$get)
names(tmp) <- name
return(tmp)
}
if(is.null(name)){
self$message("no input, returning NULL")
return(NULL)
}
# self
if(name=="self"){
return(self)
}
# in self
if(name %in% names(self)){
return(base::get(name, envir=self))
}
# private or in private
if(exists("private")){
if(name=="private"){
return(private)
}else if(name %in% names(private)){
return(base::get(name, envir=private))
}
}
# else
self$message("name not found")
return(NULL)
}
)
)
...
不是使用这样的:
a <- A$new()
a$get("private_print")()
## [1] "Ola"
您是不是应该测试您的私有方法,因为它们通常会从客户端代码中间接调用 - 例如间接地(例如从您的类的公共方法中)调用,而不是*直接调用?使方法和数据成员保持私密的关键在于,它们不能从对象实例外部访问。 – nrussell
谢谢@nrussell。对我而言,编写单元测试的目的是为了确保所有功能按预期工作。为此,单元测试最好写在尽可能最低的水平。为一个更复杂的公共方法编写单元测试(例如,在各种设置中调用私有方法数百次)使运行测试和调试失败变得更加复杂。 –