如何在 Scala 中测试私有类方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21369093/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can a private class method be tested in Scala?
提问by gdiazc
I have a companion object with a private method, like so:
我有一个带有私有方法的伴随对象,如下所示:
package com.example.people
class Person(val age: Int)
object Person {
private def transform(p: Person): Person = new Person(p.age + 1)
}
I would like to test this method, with something like:
我想测试这种方法,例如:
class PersonSpec extends FlatSpec {
"A Person" should "transform correctly" in {
val p1 = new Person(1)
val p2 = Person.transform(p1) // doesn't compile, because transform is private!
assert( p2 === new Person(2) )
}
}
Any help on having test code access private methods?
让测试代码访问私有方法有什么帮助吗?
Actually, as it is written, I might be able to create a subclass of Person, but what if Personis declared as finalor sealed?
实际上,正如所写的那样,我也许可以创建 的子类Person,但是如果Person声明为finalorsealed呢?
Thanks!
谢谢!
回答by jlegler
I am in the middle when it comes to testing everything. I don't usually test everything, but sometimes it's really useful to be able to unit test a private function without having to mangle my code to make it possible. If you're using ScalaTest, you can use the PrivateMethodTester to do it.
在测试所有内容时,我处于中间状态。我通常不会测试所有内容,但有时能够对私有函数进行单元测试而不必修改我的代码使其成为可能真的很有用。如果您使用 ScalaTest,则可以使用 PrivateMethodTester 来完成。
import org.scalatest.{ FlatSpec, PrivateMethodTester }
class PersonSpec extends FlatSpec with PrivateMethodTester {
"A Person" should "transform correctly" in {
val p1 = new Person(1)
val transform = PrivateMethod[Person]('transform)
// We need to prepend the object before invokePrivate to ensure
// the compiler can find the method with reflection
assert(p2 === p1 invokePrivate transform(p1))
}
}
That may not be exactly what you want to do, but you get the idea.
这可能不是你想要做的,但你明白了。
回答by vptheron
You could declare your method to be package private:
您可以将您的方法声明为包私有的:
private[people] def transform(p: Person): Person = new Person(p.age + 1)
If you put PersonSpec in the same package it will be able to access it.
如果您将 PersonSpec 放在同一个包中,它将能够访问它。
I leave it to you to decide if it's really wise to unit test a private method :)
我让你来决定对私有方法进行单元测试是否真的明智:)
回答by Peter Kofler
The need to unit-test private methods is a design smell.
需要对私有方法进行单元测试是一种设计味道。
Either you test them through your public API which is ok if they are small and just helper methods - or, which is more likely, it contains different logic/responsibility and should be moved to another class that is used by delegation in the Person. Then you would test the public API of that class first.
你要么通过你的公共 API 测试它们,如果它们很小并且只是辅助方法就可以了——或者,更有可能的是,它包含不同的逻辑/职责,应该移到另一个由 Person 中的委托使用的类。然后您将首先测试该类的公共 API。
See a related answerfor more details.
有关更多详细信息,请参阅相关答案。
Likely you can access it using Java/Scala reflection, but it is just a workaround for the design problem. Still, if you need to, see a related Java answer how to do that.
您可能可以使用 Java/Scala 反射来访问它,但这只是设计问题的一种解决方法。尽管如此,如果您需要,请参阅相关的 Java 答案 how to do that。
回答by Dotan
@jlegler's answer here helped me, but I still had some debugging to do before things worked, so I thought I'd write exactly what's needed for this here.
@jlegler 在这里的回答对我有帮助,但在一切正常之前我还有一些调试要做,所以我想我会在这里写下所需的内容。
to test:
去测试:
class A
object A {
private def foo(c: C): B = {...}
}
use:
利用:
val theFuncion = PrivateMethod[B]('foo)
val result = A invokePrivate theFunction(c)
Note the locations of A, B
注意A、B的位置
回答by Deil
I don't think that unit testing is about testing contract of the class - it is about testing simple functionality(unit).
我不认为单元测试是关于测试类的契约——它是关于测试简单的功能(单元)。
Also I don't think that it is a good idea to make some methods public only to make them easily testable. I believe that keeping API as narrow as possible is a good way to help other developers to use your code(IDE will not suggest private methods) and understand contract.
此外,我不认为将某些方法公开只是为了使它们易于测试是一个好主意。我相信保持 API 尽可能窄是帮助其他开发人员使用您的代码(IDE 不会建议私有方法)和理解契约的好方法。
Also we should not put everything in a single method. So sometimes we can put some logic into a private method.... and of course we want to test it as well. Testing it through the public API will increase complexity of you test.(other option is to move logic of the private method to another helper class and test it there..this class will not be used directly by developers and will not clutter up api)
此外,我们不应该将所有内容都放在一个方法中。所以有时我们可以将一些逻辑放入私有方法中......当然我们也想测试它。通过公共 API 测试它会增加你测试的复杂性。(另一种选择是将私有方法的逻辑移动到另一个辅助类并在那里进行测试..这个类不会被开发人员直接使用,也不会混淆 api)
Guys from scalatest ,I think, added PrivateMethodTester for a purpose.
我认为来自 scalatest 的人添加了 PrivateMethodTester 是出于某种目的。
回答by MikeTwo
Personally, I say make everything public and just prepend with _or __to indicate that other devs shouldn't use it.
就我个人而言,我说将所有内容公之于众,并在前面加上_或__表示其他开发人员不应该使用它。
I realize this is Scala and not Python, but regardless, "We're all consenting adults here."
我意识到这是 Scala 而不是 Python,但无论如何,“我们都同意这里的成年人。”
"Private" methods aren't actually private (for example) and certainly aren't secure, so why make life harder for what is essentially a social contract? Prepend and be done -- if another dev wants to go poking around in dark places, they either have a good reason or deserve what they get.
“私有”方法实际上并不是私有的(例如),当然也不安全,那么为什么要让本质上是社会契约的东西变得更难呢?准备并完成 - 如果另一个开发人员想要在黑暗的地方闲逛,他们要么有充分的理由,要么应得的。
回答by Marco
Generally speaking: if you want to effectively test your code, you firsthave to write it testable.
一般来说:如果你想有效地测试你的代码,你首先必须把它写成可测试的。
Scala implements the functional paradigm and extensively uses immutable objects by design, "case classes" are examples (my opinion: the Person class should be a case class).
Scala 实现了函数范式并通过设计广泛使用不可变对象,“案例类”就是例子(我认为:Person 类应该是一个案例类)。
Implementing the private methods make sense if objects has mutable state, in this case you might want to protect the state of the objects. But if objects are immutable, why implement methods as private? In your example, the method produces a copy of Person, for what reason do you want to make it private? I do not see any reason.
如果对象具有可变状态,则实现私有方法是有意义的,在这种情况下,您可能希望保护对象的状态。但是如果对象是不可变的,为什么要把方法实现为私有的呢?在您的示例中,该方法生成 Person 的副本,您出于什么原因要将其设为私有?我看不出有什么理由。
I suggest you think about this. Again, if you want to effectively test your code you have to write it testable.
我建议你考虑一下。同样,如果你想有效地测试你的代码,你必须把它写成可测试的。
回答by Septem
a possible work around would be testing private method indirectly: testing a public method which calls the private method
一种可能的解决方法是间接测试私有方法:测试调用私有方法的公共方法

