2.12 級聯mock

weixin_34402408發表於2016-12-27

出現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<Object> 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());
}

在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(); }};
}

相關文章