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

时间:2015-03-31 09:29:21

标签: java unit-testing junit mocking 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中还有另一种方法吗?

4 个答案:

答案 0 :(得分:1)

您可以使用自定义matcher执行此操作。

  

警告:使用复杂的参数匹配是合理的,尤其是自定义参数匹配器,因为它会降低测试的可读性。有时最好为传递给模拟的参数实现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);

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

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的方法时,如果您使用了常规方法来创建模拟,那么您的回答将不会返回您的内容希望在回答对象回归。

 @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);
        }

答案 3 :(得分:0)

就像在嘲讽github上提到的那样:

这似乎与第二次致电有关。我找不到正在发生的事情,但是第二次没有尝试添加模拟逻辑时,它只是调用了该方法。 替换为doReturn()。when()有效。

>>> import numpy as np
>>> np.random.seed(5)
>>> np.random.rand()
0.22199317108973948 # (1)
>>> np.random.rand()
0.8707323061773764 # (2)
>>> np.random.seed(5)  # re-seed
>>> np.random.rand()
0.22199317108973948 # same as (1)
>>> np.random.seed(5)
>>> np.random.rand()
0.22199317108973948 # same as (1) again
>>> np.random.rand()
0.8707323061773764 # same as (2)

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