通常,声明了mock对象并在Expectation中进行了record,则在replay阶段对该类其他对象的调用也会返回record的结果。也就是说,在replay阶段,JMockit并不关心调用的是哪个对象,只要是该mock类的对象就会引用record中的结果。
示例如下:
@Test
public void TestMethod(@Mocked final Dependency dependency) throws Exception {
new NonStrictExpectations() {{
dependency.intReturnMethod();
returns(1, 2, 3);
}};
Dependency dependency1 = new Dependency();
assertEquals(1, dependency1.intReturnMethod());
Dependency dependency2 = new Dependency();
assertEquals(2, dependency2.intReturnMethod());
Dependency dependency3 = new Dependency();
assertEquals(3, dependency3.intReturnMethod());
}
在大多数情况下,CodeUnderTest使用mock类的某一个对象,所以是在CodeUnderTest中创建的还是作为参数传给它的并不重要。但是,如果CodeUnderTest中包含多个mock对象,而我们需要
- 只mock其中某个对象,其它的并不mock
- 指定调用某个mock对象的方法
这时,使用 @Injectable 可以mock某个对象。当然,即使用 @Mock 注解mock该类所有对象,也有其他方法限制Expectation中的匹配。
@Injectable
public class Dependency {
public String mockMethod() {
return "realMethod";
}
}
@Test
public void TestMethod(@Injectable final Dependency mockDependency) {
new NonStrictExpectations() {{
mockDependency.mockMethod();
result = "mockMethod";
}};
assertEquals("mockMethod", mockDependency.mockMethod());
assertEquals("realMethod", new Dependency().mockMethod());
}
其他对象不受影响,正常执行原有代码。
note:
- 需要将mock对象传递给CodeUnderTest
- static方法和constructor无法被mock
声明多个mock对象
声明多个mock对象可以限制和Expectation的匹配。
示例如下:
//参数中的anotherDependency只是起到占位作用,不会被真正使用
@Test
public void TestMethod(@Mocked final Dependency mockDependency,
@Mocked Dependency anotherDependency) {
new NonStrictExpectations() {{
mockDependency.mockMethod();
result = "mockMethod";
}};
//这个会被mock
assertEquals("mockMethod", mockDependency.mockMethod());
//JMockit仍然拦截了这次调用,但是由于在Expectation中没有record,所以返回null
assertNull("realMethod", new Dependency().mockMethod());
}
这种方法看起来比较奇怪,主要用于当CodeUnderTest中包含多个Dependency类的对象,而想要测试其中某个确定对象会被调用。
mock特定constructor产生的实例
有两种方式可以实现这个效果,方式1:
@Test
//mockDependency不会被使用
public void TestMethod(@Mocked Dependency mockDependency) {
new NonStrictExpectations() {{
Dependency dependency1 = new Dependency("dependency1");
dependency1.mockMethod(); result="dependency1";
Dependency dependency2 = new Dependency("dependency2");
dependency2.mockMethod(); result="dependency2";
}};
//可以创建多个对象,会匹配到同一个Expectation
assertEquals("dependency1", new Dependency("dependency1").mockMethod());
assertEquals("dependency1", new Dependency("dependency1").mockMethod());
assertEquals("dependency2", new Dependency("dependency2").mockMethod());
//JMockit仍然拦截了这次调用,但是由于在Expectation中没有record,所以返回null
assertNull(new Dependency("dependency2").mockMethod());
}
方式2:
@Test
public void TestMethod(@Mocked final Dependency mockDependency1,
@Mocked final Dependency mockDependency2) {
new NonStrictExpectations() {{
new Dependency("dependency1");
result = mockDependency1;
new Dependency("dependency2");
result = mockDependency2;
mockDependency1.mockMethod();
result = "dependency1";
mockDependency2.mockMethod();
result = "dependency2";
}};
assertEquals("dependency1", new Dependency("dependency1").mockMethod());
assertEquals("dependency1", new Dependency("dependency1").mockMethod());
assertEquals("dependency2", new Dependency("dependency2").mockMethod());
assertNull("dependency3", new Dependency("dependency3").mockMethod());
}
两种方法等效。