6

我目前在一个项目中使用 R6 类。

我想编写单元测试来测试我正在使用的私有方法的功能(最好不要通过使用这些私有方法的更复杂的公共方法)。

但是,我似乎无法访问私有方法。

我怎样才能最好地做到这一点?

谢谢!

4

3 回答 3

14

这是一个不需要环境黑客或更改您要测试的类的解决方案,而是创建一个为您进行测试的新类。

R6中,派生类可以访问private其基类的方法(与 inC++Java您需要protected关键字来归档相同结果的地方不同)。因此,您可以编写一个TesterClass派生自您要测试的类的类。例如:

ClassToTest <- R6::R6Class(
  private = list(
    privateMember = 7,
    privateFunction = function(x) {
      return(x * private$privateMember)
    }
  )
)

TesterClass <- R6::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

这种方法的一个优点是您可以将详细的测试结果保存在TesterClass.

于 2017-06-20T01:13:32.630 回答
3

目前有一种方法可以访问 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
于 2016-07-25T21:59:40.057 回答
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"
于 2016-09-24T23:10:30.457 回答