Mockito允许不同的参数类型模拟重载方法



对于JUnit测试,我想模拟一个重载的方法。不过,没有必要在mockbuilder中实现几个方法。我想做这样的事情:

Mockito.when(mock.getSomeInfo(Mockito.any(ArgumentType1.class) OR Mockito.any(ArgumentType2.class), Mockito.any(ArgumentType3.class))).then(new Answer<AnswerType>() {..}

我知道它不适用于OR语句,但在Mockito中有其他方法可以做到这一点吗?

如mockito github上所述:

这似乎与第二次打电话有关。我找不到发生了什么,但第二次没有尝试添加mock逻辑,它只是调用了方法用doReturn()替换。when()有效

    doReturn(expected1).when(overloadedMethods).getString(any());
    doReturn(expected2).when(overloadedMethods).getString(any(), any());

https://github.com/mockito/mockito/issues/1496#issuecomment-423310950 DavidTanner

您可以使用自定义匹配器来完成此操作。

警告:使用复杂的参数匹配要合理,尤其是自定义参数匹配器,因为这会降低测试的可读性。有时,最好为传递给mock的参数实现equals()(Mockito自然会使用equals(()进行参数匹配)。这样可以使测试更干净。


public class TypeOrMatcher extends ArgumentMatcher<Object> {
  private final List<Class<?>> clazzes;
  public TypeOrMatcher(Class<?>...clazzes) {
    this.clazzes = new ArrayList<Class<?>>(clazzes);
  }
  public boolean matches(Object actual) {
    if (actual == null) {
      return false;
    }
    Class<?> actualClass = actual.getClass();
    for (Class<?> clazz : clazzes) {
      if (clazz.isAssignableFrom(actualClass) {
        return true;
      }
    }
    return false;
  }
}
TypeOrMatcher isTypeOneOrTwo = new TypeOrMatcher(
    ArgumentType1.class, ArgumentType2.class); 
Some mockObj = mock(Some.class);
when(mockObj.someMethod(argThat(isTypeOneOrTwo), any(ArgumentType3.class))
    .thenReturn(true);

您可以预先创建要返回的答案对象,然后返回此答案。

class A {
    public int test(final String s) {
        return 0;
    }
    public int test(final int i) {
        return 0;
    }
}

并且在测试方法中:

public void testAtest() {
    final A a = Mockito.mock(A.class);
    final Answer<Integer> answer = new Answer<Integer>() {
        @Override
        public Integer answer(final InvocationOnMock invocation) throws Throwable {
            return 0;
        }
    };
    Mockito.when(a.test(Matchers.anyInt())).then(answer);
    Mockito.when(a.test(Matchers.anyString())).then(answer);
}

例如,我有一个将从测试方法调用的服务类:

public interface AService{
   public ReturnObject addNewItem(String param1, String param2);
   public ReturnObject addNewItem(String param1, String param2, boolean isOk);
}

MainServiceImpl类中有一个方法将调用一个重载方法,如下所示:

@Service("mainService")
public class MainServiceImpl implements MainService {
    @Autowired
    private AService aService;
    public ReturnObject saveItem(String itemName, String itemCode){
        return  aService.addNewItem(itemName, itemCode);
    }
}

因此,当我们必须为saveItem编写单元测试时,该方法已经将重载方法调用为addNewItem,如果您使用正常方式创建mock,那么您的答案将不会在答案对象返回中返回您想要的内容。

@RunWith(PowerMockRunner.class)
@PrepareForTest({ })
public class ItemTest{
    @Test
    public void testSaveItem() throws Exception {
       //create a real object of MainServiceImpl 
       MainServiceImpl  mainService = new MainServiceImpl();
       //create a normal way for a mocking object
       AService aService = Mockito.mock(AService.class);
       // Add mock object to MainServiceImpl instance
       ReflectionTestUtils.setField(mainService, "aService", aService);
       //Mock when aService call to addNewItem() method
       PowerMockito.when(aService , "addNewItem", Mockito.anyString(), Mockito.anyString()).then(new Answer<ReturnObject>() {
            @Override
            public ReturnObject answer(InvocationOnMock invocation) throws Throwable {
                return new ReturnObject("saveOK");
            }
        });
        ReturnObject returnObj = mainService.saveItem("Book", "Code123");
        Assert.assertNotNull(returnObj);
    }
}

尝试用以下testSaveItem替换上面的testSaveItem,然后成功:

@Test
public void testSaveItem() throws Exception {
    //create a real object of MainServiceImpl 
    MainServiceImpl  mainService = new MainServiceImpl();
    //create a special way for a mocking object by add 
    //the answer at create the mock object
    final Answer<ReturnObject> answer = new Answer<ReturnObject>() {
        @Override
        public ReturnObjectanswer(final InvocationOnMock invocation)    throws Throwable {
            return new ReturnObject("saveOK");
        }
    };
    AService aService = Mockito.mock(AService.class, answer);
    // Add mock object to MainServiceImpl instance
    ReflectionTestUtils.setField(mainService, "aService", aService);
    //Mock when aService call to addNewItem() method
    PowerMockito.when(aService , "addNewItem", Mockito.anyString(), Mockito.anyString()).then(new Answer<ReturnObject>() {
            @Override
            public ReturnObject answer(InvocationOnMock invocation) throws Throwable {
                return new ReturnObject("saveOK");
            }
        });
    ReturnObject returnObj = mainService.saveItem("Book", "Code123");
    Assert.assertNotNull(returnObj);
}

相关内容

  • 没有找到相关文章

最新更新