Java 单元测试:替换被测私有方法
运行 JUnit 测试时是否有任何方法可以替换私有方法中的逻辑?
一些背景知识:我们有一些与 OSGi 容器内的包交互的私有方法。这在单元测试中不可用,因此该方法将失败。
我们已经研究过 JMockIt,但方法替换功能似乎想要强制您替换类中相互调用的所有方法。
实现将是这样的:
public final doSomething() {
firstThing();
secondThing();
}
private firstThing() {
// normal code
}
private secondThing() {
// code which is unavailable in a unit test
}
单元测试将指定 secondaryThing() 的新实现:
// replace secondThing() in impl with this secondThing()
private secondThing() {
// dummy code
}
// run tests
Is there any way of replacing the logic within a private method when running a JUnit test?
A bit of background: we have some private methods which interact with bundles within an OSGi container. This is not available in the unit test therefore the methods will fail.
We have looked at JMockIt but the method replace functionality seems to want to force you to replace all the methods in the class which call one another.
The implementation would be something like this:
public final doSomething() {
firstThing();
secondThing();
}
private firstThing() {
// normal code
}
private secondThing() {
// code which is unavailable in a unit test
}
And the unit test would specify the new implementation of secondThing():
// replace secondThing() in impl with this secondThing()
private secondThing() {
// dummy code
}
// run tests
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你当然可以用JMockit解决这种情况。
一种方法是定义一个“模拟”类,例如:
只有模拟类中的 SecondThing() 方法才会被 JMockit 替换。
还可以使用 JMockit Expectations API 进行部分模拟。
You certainly can solve this situation with JMockit.
One way would be to define a "mock-up" class, for example:
Only the
secondThing()
method in the mocked class will be replaced by JMockit.The JMockit Expectations API could also be used, with partial mocking.
您将实现与 osgi 对象的创建耦合(在 secondaryThing() 或类本身内执行)。如果您从外部将实现传递到类中,则可以在测试时使用存根/模拟。
You are coupling your implementation to the creation of the osgi object (doing it inside secondThing() or the class itself). If you passed the implementation into your class from the outside, you could use a stub/mock when testing instead.
我还认为依赖注入可以解决这个问题。
如果您不想在项目中使用另一个框架,并且这是唯一会带来麻烦的地方,您可以为 secondaryThing 定义一个接口,并为其提供 2 个实现,一个用于原始代码,另一个用于单元测试的空实现。
I also think dependency injection would solve this problem.
If you don't want another framework in your project and this is the only place which makes trouble, you could define an interface for secondThing and have 2 implementations for that, one for the original code and an empty one for the unittest.
我的建议 - 重新设计你的应用程序。如果您想更改
private
方法的行为:protected
/public
并在类似模拟的对象中覆盖它,解决方法可能是某种字节码操作技术,但我不推荐这样做。
My advice - redesign your application. If you want to change the behaviour of a
private
method:protected
/public
and override it in a mock-like objectA workaround may be some byte-code manipulation technique, but I don't recommend such.
有一个很好的存根模式
ProductionClass.java:BlaTest.java
(与生产类相同的包):
一件不同的事情。我在您的示例代码中看到了最终修饰符。请注意使用 final 修饰符。它们对于可测试性来说是邪恶的。仅在确实必要时才使用。
there is a nice stub-pattern
ProductionClass.java:
BlaTest.java (same package as production class):
One different thing. I saw a final modifier in your sample-code. Beware of using final modifier. They are evil for testability. Only use if really really necessary.