Issue
I'm currently trying to create tests for our Servlets. I've mocked HttpServletRequest
, HttpServletResponse
and an object serving as a database handler. In the test for the doPost
method, my wish is to compare the values from the Json object and the ArrayList sent to the database object.
The 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);
}
The test:
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());
}
When I'm running the test it gives me NullpointerException
at the line
verify(dbMock).addWidgetStatus(captor.capture());
What am I doing wrong? I've looked at several examples with the same usage of the ArgumentCaptor
. Perhaps this is just a minor error?
Solution
If you use the MockitoJUnitRunner
to run your test, then an ArgumentCaptor
will be created for you, and there's no need to initialise it explicitly. If you do that, then you can also use the @Mock
annotation to create your mock objects, that is, you don't need the mock
static method any more. Your test class would then begin like this.
@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 addresses the issue of whether to use MockitoJUnitRunner
, or an explicit call to MockitoAnnotations.initMocks
.
Just a side note - your test methods will be much easier to read if you use variable names that clearly indicate that your objects are mocks, like I've done here. Otherwise, in a long test class with many different variables, it's easy to lose track of which variables reference mocks, and which reference "real" objects.
Answered By - Dawood ibn Kareem