2.12|2.12 级联mock

出现obj1.getObj2(...).getYetAnotherObj().doSomething(...)时可能需要mock多个对象。对于一个mock对象:

  • Expectation中进行了record,则会返回record的result;
  • 如果没有record,JMockit会自动创建一个返回被注解@Injectable的子对象
public class Dependency {public CascadeDependency getCascadeDependency() { //JMockit会拦截这个方法,返回一个非null对象 return null; }public CascadeDependency getAnotherCascadeDependency() { //JMockit会拦截这个方法,返回一个非null对象 return null; }public String getString() { //仍旧返回null return null; }public Object getObject() { //仍旧返回null return null; }public List getList() { //返回empty集合 return null; } }
@Test public void TestMethod(@Mocked Dependency dependency) {CascadeDependency first = dependency.getCascadeDependency(); CascadeDependency second = dependency.getCascadeDependency(); //调用另一个方法 CascadeDependency third = dependency.getAnotherCascadeDependency(); //所有都不会为null assertNotNull(first); assertNotNull(second); assertNotNull(third); //相同方法返回JMockit创建的同一个对象 assertSame(first, second); //不同方法返回JMockit创建的同一个对象 assertNotSame(first, third); //String返回null assertNull(dependency.getString()); //Object返回null assertNull(dependency.getObject()); //返回empty集合 assertNotNull(dependency.getList()); assertEquals(0, dependency.getList().size()); }

@Test public void TestMethod(@Mocked Dependency dependency, @Mocked CascadeDependency cascadeDependency) {CascadeDependency first = dependency.getCascadeDependency(); CascadeDependency second = dependency.getAnotherCascadeDependency(); //因为子对象也@Mocked,所以会返回同一个对象 assertSame(first, second); }

JMockit返回的非空对象实际上进行了@Injectable标识,所以:
@Test public void TestMethod(@Mocked Dependency dependency) {//虽然CascadeDependency没有出现在参数中, //但是JMockit对其进行了@Injectable //而由于没有在Expectation中record mockMethod的result,所以返回空 assertNull(dependency.getCascadeDependency().mockMethod()); //不影响CascadeDependency的其他实例 assertNotNull(new CascadeDependency().mockMethod()); }

也可以在Expectation中使用result指定返回对象,从而禁止JMockit自动生成。
@Test public void TestMethod(@Mocked final Dependency dependency) {//在Expectation中指定了返回结果,因此JMockit不会生成CascadeDependency new NonStrictExpectations(){{ dependency.getCascadeDependency(); result = null; result = new CascadeDependency(); }}; //第一次返回null assertNull(dependency.getCascadeDependency()); //第二次返回新对象 assertNotNull(dependency.getCascadeDependency().mockMethod()); }

mock级联调用特别适合static factory,getCurrentInstance()永远不会返回null。
@Test public void TestMethod(@Mocked final Dependency dependency) { assertSame(dependency, dependency.getCurrentInstance()); }

【2.12|2.12 级联mock】在Builder模式中也很方便验证,
@Test public void createOSProcessToCopyTempFiles(@Mocked final ProcessBuilder pb) throws Exception{ Process copy = new ProcessBuilder().command(cmdLine).directory(wrkDir).inheritIO().start(); new Verifications() {{ pb.command(withSubstring("copy")).start(); }}; }

    推荐阅读