使用 any() 或 anyList() 时,使用 ArrayList/List 参数清除方法失败
Stubbing out method with ArrayList/List param fails when using any() or anyList()
我有一个 java class.
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));
这 returns 一个 NullPointerException。我也试过任何(List.class),任何(数组List.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).
您的 NullPointerException 在 存根 期间被抛出,而不是在测试期间。
这是因为 Matchers.any()
实际上是 returns 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!(虽然公认不是很清楚)。
在 when()
中包含此语句 blah.testMe()
,它调用真正的方法:
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));
}
您应该重新考虑使用 spy
、mock
等。当您有外部系统、休息 Web 服务、您不想在单元测试期间调用的数据库时,应该使用这些设施。在像这样的简单场景中,只需创建一些测试输入并检查输出。
@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。
我有一个 java class.
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));
这 returns 一个 NullPointerException。我也试过任何(List.class),任何(数组List.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).
您的 NullPointerException 在 存根 期间被抛出,而不是在测试期间。
这是因为 Matchers.any()
实际上是 returns 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!(虽然公认不是很清楚)。
在 when()
中包含此语句 blah.testMe()
,它调用真正的方法:
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));
}
您应该重新考虑使用 spy
、mock
等。当您有外部系统、休息 Web 服务、您不想在单元测试期间调用的数据库时,应该使用这些设施。在像这样的简单场景中,只需创建一些测试输入并检查输出。
@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。