使用 Mockito、spy 和 Reflection 在 Map 对象上进行单元测试

use*_*782 4 java reflection unit-testing mockito

我的情况有点复杂,不知道如何处理。有一个带有私有变量映射的对象(该对象已被初始化)。这个类有一系列对地图的操作。

我需要编写一个单元测试。它将获取私有变量,模拟(或监视)它,对其执行一些操作,并验证操作的顺序。什么是最好的方法?

public class A{
   private Map<String, String> map = new Map()<>;

   public void method1(){
     map.put("a", "A");
   }       

   public void method2(){ 
     if(map.size() > 0){
        map.put("b", "B");
     }

}
...
public class UnitTester{
@Test
public void test(){
    A ainstance = new A();
    Map<String,String> mock = mock(Map.class); //OR Map<String,String> mock = spy(Map.class); 

    Field f= A.class.getDeclaredField("map");
    f.setAccessible(true);
    f.set(ainstance, mock);

    ainstance.method1();
    ainstance.method2();

    InOrder inOrder = inOrder(mock);
    inOrder.verify(mock, times(2), put(anyString(), anyString()));  //Does not work

}
Run Code Online (Sandbox Code Playgroud)

map.put不会在地图中添加任何内容。不确定这是因为它是反射对象还是有其他原因。

Mac*_*ski 6

您可以利用注释,而不是手动使用反射。另外你应该改变一下你的验证方式。最后我会使用 useSpy而不是,Mock因为在我看来它更合适:

public class UnitTester{

@InjectMocks
private A aInstance;

@Spy
private Map mapSpy = new HashMap();

@Before
public void init(){
    MockitoAnnotations.initMocks(this);
}

@Test
public void test(){
    // Act   

    ainstance.method1();
    ainstance.method2();

    InOrder inOrder = inOrder(mapSpy);
    inOrder.verify(mapSpy).put("a", "A"));      
    inOrder.verify(mapSpy).put("b", "B"));     
}
Run Code Online (Sandbox Code Playgroud)

如果您需要进一步阅读,我写了一篇关于Mockito 间谍InOrder Verification的文章。