我目前正在尝试为我们的Servlet创建测试。我嘲笑了HttpServletRequest
,HttpServletResponse
和一个充当数据库处理程序的对象。在doPost
方法的测试中,我希望比较Json对象和发送到数据库对象的ArrayList的值。
servlet:
public class WidgetStatusServlet extends HttpServlet {
private DBController db = new DBController();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/json");
JsonParser parser = new JsonParser();
JsonElement tradeElement = parser.parse(request.getParameter("widgetdata"));
JsonArray json = tradeElement.getAsJsonArray();
Gson gson = new Gson();
Type listType = new TypeToken<List<WidgetStatus>>() {
}.getType();
ArrayList<WidgetStatus> widgets = gson.fromJson(json, listType);
Iterator<WidgetStatus> iterator = widgets.iterator();
System.out.println("Widgets");
while (iterator.hasNext()) {
WidgetStatus node = (WidgetStatus) iterator.next();
System.out.println(node);
}
db.addWidgetStatus(widgets);
}
测试:
public class WidgetStatusServletTest {
@Captor
private ArgumentCaptor<ArrayList<WidgetStatus>> captor;
private DBController dbMock = mock(DBController.class);
private HttpServletRequest request = mock(HttpServletRequest.class);
private HttpServletResponse response = mock(HttpServletResponse.class);
Repository repository = mock(Repository.class);`
@Test
public void doPost_ShouldVerifyWidgetsIsProvided() throws Exception {
final WidgetStatus widget1 = new WidgetStatus("id1", "div_id1", "5", "5", "1", "2", false);
final WidgetStatus widget2 = new WidgetStatus("id2", "div_id2", "2", "1", "3", "1", true);
when(request.getParameter("widgetdata")).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
ArrayList<WidgetStatus> array = new ArrayList<WidgetStatus>();
array.add(widget1);
array.add(widget2);
String json = new Gson().toJson(array);
return json;
}
});
new WidgetStatusServlet().doPost(request, response);
verify(dbMock).addWidgetStatus(captor.capture());
assertNotNull(captor.getAllValues());
}
当我运行测试时,它会在
行给我NullpointerException
verify(dbMock).addWidgetStatus(captor.capture());
我做错了什么?我查看了几个与ArgumentCaptor
使用相同的示例。也许这只是一个小错误?
答案 0 :(得分:10)
如果您使用MockitoJUnitRunner
来运行测试,那么将为您创建ArgumentCaptor
,并且无需明确初始化它。如果这样做,那么您也可以使用@Mock
注释来创建模拟对象,也就是说,您不再需要mock
静态方法。然后你的测试类就会这样开始。
@RunWith(MockitoJUnitRunner.class)
public class WidgetStatusServletTest {
@Captor private ArgumentCaptor<ArrayList<WidgetStatus>> captor;
@Mock private DBController mockController;
@Mock private HttpServletRequest mockRequest;
@Mock private HttpServletResponse mockResponse;
@Mock private Repository mockRepository;
This question解决了是否使用MockitoJUnitRunner
或明确调用MockitoAnnotations.initMocks
的问题。
只是旁注 - 如果您使用明确表明您的对象是模拟的变量名称,您的测试方法将更容易阅读,就像我在这里做的那样。否则,在具有许多不同变量的长测试类中,很容易忽略哪些变量引用模拟,哪些变量引用“真实”对象。
答案 1 :(得分:3)
标注为注释@Mock
和@Captor
(以及@Spy
和@InjectMocks
)的字段将由Mockito自动初始化,但仅限于您致电MockitoAnnotations.initMocks(this)
在测试课上。
您可以在setUp
(JUnit3)或@Before
方法(JUnit4)中自行完成此操作,或使用@RunWith(MockitoJUnitRunner.class)
注释您的测试用例以获得自动初始化和验证。
答案 2 :(得分:0)
您没有初始化captor
对象,因此无法执行其capture()
方法。您必须在调用其方法之前初始化对象。
答案 3 :(得分:0)
似乎ArgumentCaptor
未初始化。
使用mockito注释时,它们由
初始化添加MockitoAnnotations.initMocks(this);
行
设置方法
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
或者通过向TestClass添加@RunWith(MockitoJUnitRunner.class)
注释。
答案 4 :(得分:0)
如果您使用的是 Junit 5 jupitor 并且诸如 @Spy @Captor 和 @Mock 之类的注释对您不起作用,那是因为“RunWith”已被删除,您现在需要使用“@ExtendWith”来使用扩展注释。
因此,使用 @ExtendWith(MockitoExtension.class)
而不是 @RunWith(MockitoJUnitRunner.class)
将为您解决问题,并且注释将按预期工作。