使用any()或anyList()时,使用ArrayList / List参数存根方法失败

时间:2019-05-31 18:46:38

标签: java testing mockito spy

我有一个Java类。

class Blah{
        public Blah(){

        }
        public String testMe(List<String> s){
            return new String("hello "+s.get(0));
        }


        public String testMeString(String s){
            return new String("hello "+s);
        }


    }

我无法尝试存根并成功测试testMe方法。请注意,我只是想了解Java中的模拟。例如,我尝试过:

    @Test
    public void testTestMe(){
        Blah blah = spy(new Blah());
        ArrayList<String> l = new ArrayList<String>();
        l.add("oopsie");
        when(blah.testMe(Matchers.any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMe(l));

这将返回NullPointerException。我也尝试了any(List.class),any(ArrayList.class)。我也尝试过使用anyList(),但这给了我IndexOutOfBounds错误。我究竟做错了什么? 有趣的是,我的testMeString工作正常。如果我愿意

@Test
    public void testTestMeString(){
        Blah blah = spy(new Blah());
        when(blah.testMeString(any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMeString("lala"));
}

测试通过any()和any(String.class)。

3 个答案:

答案 0 :(得分:3)

blah.testMe()中包含此语句when()时,它将调用实数方法:

when(blah.testMe(Matchers.any())).thenReturn("intercepted");

为避免这种情况,您应该使用doReturn(...).when(...).methodToInvoke()模式。

doReturn("intercepted").when(blah).testMe(Matchers.any()));

您会注意到,使用以下语法:blah.testMe()语句未在任何地方指定。因此不被称为。

除了这个问题,我认为您不需要任何间谍即可测试此方法。
间谍是模拟中非常特殊的工具,只有在您别无选择时才使用间谍:您需要模拟被测对象,这是一种不好的做法,您无法重构实际代码。

但是在这里您可以做:

@Test
public void testTestMe(){
    Blah blah = new Blah();
    ArrayList<String> l = new ArrayList<String>();
    l.add("oopsie");
    assertEquals("hello oopsie",blah.testMe(l));
 }

答案 1 :(得分:2)

您应该重新考虑使用spymock等。当您具有外部系统,剩余的Web服务,不想在单元测试期间调用的DB时,应使用这些功能。在像这样的简单场景中,只需创建一些测试输入并检查输出即可。

@Test public void testTestMeString(){
 //given
  List<String> list = Arrays.asList("aaa");
 //when
 String result = blah.testMe(list);
 //then
 assertEquals(result, "hello aaa");
 }

如果您对given, when, then感兴趣,请检查BDD。

答案 2 :(得分:1)

您的NullPointerException是在 stubbing 期间而不是在测试期间抛出的。

这是因为Matchers.any()实际上返回了null,因此,如果在调用实型方法时使用它,则会将null作为参数传递。 testMeString之所以起作用,是因为null + s不会导致NullPointerException(而是使用字符串"null")。

代替:

when(blah.testMe(any())).thenReturn("intercepted");

您需要使用

doReturn("intercepted").when(blah).testMe(any());

在Mockito文档中,它被记录为Important gotcha on spying real objects!(尽管公认不是很清楚)。