我在Java 1.7上使用JMockit 1.15。
我想验证一些经过测试的代码首先创建一个特定类的新实例( ExampleClass ),然后在该实例上调用一个方法。 我尝试了许多方法,使用验证,期望,@Mocked,@ Injectable以多种方式,但我无法成功。
以下是一个例子。
ExampleClass 是一个类;我要模仿它,我想验证它是如何使用的。
public class ExampleClass {
final double id = Math.random();
public ExampleClass() {
}
public void doSomething() {
System.out.println("I did something - " + id);
}
}
ExampleClassUser 包含我想要测试的逻辑。
请注意,wrongUsage()构建了ExampleClass的两个实例,但总是在第一个上调用doSomething()。
public class ExampleClassUser {
public void rightUsage() {
final ExampleClass exampleClass1 = new ExampleClass();
exampleClass1.doSomething();
final ExampleClass exampleClass2 = new ExampleClass();
exampleClass2.doSomething();
}
public void wrongUsage() {
final ExampleClass exampleClass1 = new ExampleClass();
exampleClass1.doSomething();
final ExampleClass exampleClass2 = new ExampleClass();
exampleClass1.doSomething();
}
}
ExampleClassUserTest 是我想要构建的测试。 它应检查每个方法是否调用rightUsage()或wrongUsage()
应用于rightUsage()时测试应该成功,并且当应用于wrongUsage()时测试失败。
当然,我的测试无法做到这一点,因为它只是检查是否正在创建新实例并且执行了两个方法调用,但是**没有检查方法调用执行的实例“
import mockit.FullVerificationsInOrder;
import mockit.Mocked;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(mockit.integration.junit4.JMockit.class)
public class ExampleClassUserTest {
@Test
public void testUsage(final @Mocked ExampleClass exampleClass) {
//new ExampleClassUser().rightUsage();
new ExampleClassUser().wrongUsage();
new FullVerificationsInOrder() {{
new ExampleClass();
exampleClass.doSomething();
new ExampleClass();
exampleClass.doSomething();
}};
}
}
答案 0 :(得分:1)
使用JMockit 1.17或更新版本,以下版本的测试将起作用(即,它将按预期失败):
@Test
public void testUsage(@Mocked ExampleClass exampleClass)
{
new ExampleClassUser().wrongUsage();
new FullVerificationsInOrder() {{
ExampleClass e1 = new ExampleClass(); // matches first new instance
e1.doSomething(); // matches only on instances equivalent to "e1"
// Same as before, now for the second instance.
ExampleClass e2 = new ExampleClass();
e2.doSomething(); // fails with a "missing invocation"
}};
}
答案 1 :(得分:0)
测试实例化对象的方法有点困难,因为在您无法访问新创建的实例的方法之外。对此的解决方案是使用Factory
创建ExampleClass
实例,工厂将其作为依赖项传递给ExampleClassUser
。现在您可以控制,因为您可以模拟工厂以返回所需的任何对象(模拟,自定义单元测试对象等),并且由于您可以访问这些对象,因此可以对它们进行断言。
另一种方法,如果你不强烈需要确保调用了对象/方法,那就是不要断言调用正确的对象/方法,而是断言这些调用的效果。这将有利于将测试与方法实现分离。只有当doSomething()
具有无需访问对象时可以检测到的副作用时,此方法才可行,并且可能涉及复杂的设置。
例如,如果doSomething()
返回素数并且每次调用它,则返回下一个素数(第一个调用将返回2,第二个3,依此类推),测试方法将添加两个数字,返回它们(是的,我知道愚蠢的例子),您可以检测是否在两个不同的对象上调用doSomething()
,因为它们的总和是4.如果在同一个对象上调用doSomething()
,则返回结果是5。