在运行JUnit测试时,有没有办法在私有方法中替换逻辑?
一些背景知识:我们有一些私有方法可以与OSGi容器中的bundle进行交互。这在单元测试中不可用,因此方法将失败。
我们已经查看了JMockIt但是方法替换功能似乎想要强制你替换类中相互调用的所有方法。
实施将是这样的:
public final doSomething() {
firstThing();
secondThing();
}
private firstThing() {
// normal code
}
private secondThing() {
// code which is unavailable in a unit test
}
单元测试将指定secondThing()的新实现:
// replace secondThing() in impl with this secondThing()
private secondThing() {
// dummy code
}
// run tests
答案 0 :(得分:6)
你当然可以用JMockit解决这个问题。 一种方法是定义“模拟”类,例如:
public class MyTest
{
@Test
public void testDoSomething()
{
new MockUp<ClassWhichDependsOnOtherBundles>()
{
@Mock
void secondThing()
{
// do anything here
}
};
new ClassWhichDependsOnOtherBundles().doSomething();
}
}
只有模拟类中的secondThing()
方法将被JMockit替换。
也可以使用JMockit Expectations API,部分模拟。
答案 1 :(得分:3)
您正在将您的实现与osgi对象的创建耦合(在secondThing()或类本身内部执行)。如果您从外部将实现传递到您的类中,则可以在测试时使用存根/模拟。
答案 2 :(得分:2)
我也认为依赖注入会解决这个问题。 如果您不希望项目中有另一个框架,并且这是唯一一个出现问题的地方,您可以为secondThing定义一个接口,并为其创建2个实现,一个用于原始代码,另一个用于unittest。
答案 3 :(得分:1)
我的建议 - 重新设计您的应用程序。如果要更改private
方法的行为:
protected
/ public
并在类似模拟的对象中覆盖它解决方法可能是一些字节码操作技术,但我不建议这样做。
答案 4 :(得分:-1)
有一个很好的存根模式
ProductionClass.java:
public class ProductionClass {
...
//default visibility to make it available for stubbing
void firstThing(){...}
...
}
BlaTest.java(与生产类相同的包):
public class BlaTest {
@Test
void test_xx(){
//use stubbed impl
ProductionClass sut = new ProductionClassStubbed();
sut.doSomething();
}
}
class ProductionClassStubbed extends ProductionClass{
@Override
void firstThing(){
//stub out fill in what you want (like dummy behaviour)
}
}
一个不同的事情。我在示例代码中看到了一个final修饰符。注意使用最终修饰符。它们对于可测性是邪恶的。只有在真的有必要时才使用。