我怎样才能让一个方法返回传递给它的参数?
考虑一个方法签名,如:
public String myFunction(String abc);
Mockito可以帮助返回方法收到的相同string吗?
您可以在Mockito中创build答案。 我们假设,我们有一个名为Application的接口,其方法为myFunction。
public interface Application { public String myFunction(String abc); }
这是Mockito答案的testing方法:
public void testMyFunction() throws Exception { Application mock = mock(Application.class); when(mock.myFunction(anyString())).thenAnswer(new Answer<String>() { @Override public String answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); return (String) args[0]; } }); assertEquals("someString",mock.myFunction("someString")); assertEquals("anotherString",mock.myFunction("anotherString")); }
由于Mockito 1.9.5和Java 8通过使用lambda函数有一个更简单的方法:
when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);
如果你有Mockito 1.9.5或更高版本,有一个新的静态方法可以为你创buildAnswer
对象。 你需要写一些类似的东西
when(myMock.myFunction(anyString())).then(returnsFirstArg());
或者可选地
doAnswer(returnsFirstArg()).when(myMock).myFunction(anyString());
请注意,在returnsFirstArg()
类中, returnsFirstArg()
方法是静态的,这对于Mockito 1.9.5是新的; 所以你需要正确的静态导入。
使用Java 8,即使使用老版本的Mockito,也可以创build一个单行的答案:
when(myMock.myFunction(anyString()).then(i -> i.getArgumentAt(0, String.class));
当然,这不像使用David Wallace所build议的AdditionalAnswers
那样有用,但是如果你想要“随时”变换参数,可能会有用。
我有一个非常类似的问题。 我们的目标是嘲笑一个持久化Object的服务,并且可以通过它们的名字来返回它们。 该服务如下所示:
public class RoomService { public Room findByName(String roomName) {...} public void persist(Room room) {...} }
服务模拟使用地图来存储房间实例。
RoomService roomService = mock(RoomService.class); final Map<String, Room> roomMap = new HashMap<String, Room>(); // mock for method persist doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); if (arguments != null && arguments.length > 0 && arguments[0] != null) { Room room = (Room) arguments[0]; roomMap.put(room.getName(), room); } return null; } }).when(roomService).persist(any(Room.class)); // mock for method findByName when(roomService.findByName(anyString())).thenAnswer(new Answer<Room>() { @Override public Room answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); if (arguments != null && arguments.length > 0 && arguments[0] != null) { String key = (String) arguments[0]; if (roomMap.containsKey(key)) { return roomMap.get(key); } } return null; } });
我们现在可以在这个模拟上运行我们的testing。 例如:
String name = "room"; Room room = new Room(name); roomService.persist(room); assertThat(roomService.findByName(name), equalTo(room)); assertNull(roomService.findByName("none"));
用Java 8, 史蒂夫的答案可以成为
public void testMyFunction() throws Exception { Application mock = mock(Application.class); when(mock.myFunction(anyString())).thenAnswer( invocation -> { Object[] args = invocation.getArguments(); return args[0]; }); assertEquals("someString", mock.myFunction("someString")); assertEquals("anotherString", mock.myFunction("anotherString")); }
编辑:甚至更短:
public void testMyFunction() throws Exception { Application mock = mock(Application.class); when(mock.myFunction(anyString())).thenAnswer( invocation -> invocation.getArgument(0)); assertEquals("someString", mock.myFunction("someString")); assertEquals("anotherString", mock.myFunction("anotherString")); }
我使用类似的东西(基本上是相同的方法)。 有时,有一个模拟对象返回某些input的预定义输出是有用的。 这是这样的:
private Hashtable<InputObject, OutputObject> table = new Hashtable<InputObject, OutputObject>(); table.put(input1, ouput1); table.put(input2, ouput2); ... when(mockObject.method(any(InputObject.class))).thenAnswer( new Answer<OutputObject>() { @Override public OutputObject answer(final InvocationOnMock invocation) throws Throwable { InputObject input = (InputObject) invocation.getArguments()[0]; if (table.containsKey(input)) { return table.get(input); } else { return null; // alternatively, you could throw an exception } } } );
您可能希望将verify()与ArgumentCaptor结合使用以确保在testing中执行,并使用ArgumentCaptor来评估参数:
ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class); verify(mock).myFunction(argument.capture()); assertEquals("the expected value here", argument.getValue());
参数的值显然可以通过argument.getValue()进一步操作/检查/不pipe。