Mockito ArgumentCaptor在verify()上给出NullpointerException



我目前正在尝试为我们的Servlet创建测试。我已经模拟了HttpServletRequestHttpServletResponse和一个充当数据库处理程序的对象。在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相同的例子。也许这只是一个小错误?

如果使用MockitoJUnitRunner运行测试,则会为您创建一个ArgumentCaptor,无需显式初始化。如果您这样做,那么您还可以使用@Mock注释来创建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;

这个问题解决了是使用MockitoJUnitRunner还是显式调用MockitoAnnotations.initMocks的问题。

只是一个附带的注意事项-如果您使用的变量名称清楚地表明您的对象是mock,那么您的测试方法将更容易阅读,就像我在这里所做的那样。否则,在一个有很多不同变量的长测试类中,很容易忘记哪些变量引用mock,哪些引用"真实"对象。

标记有注释@Mock@Captor(以及@Spy@InjectMocks)的字段将由Mockito自动初始化,但前提是您在测试类中调用MockitoAnnotations.initMocks(this)

您可以在setUp(JUnit3)或@Before方法(JUnit4)中自己完成这项工作,或者用@RunWith(MockitoJUnitRunner.class)注释您的测试用例以获得自动初始化和验证。

ArgumentCaptor似乎没有初始化。

当使用mockito注释时,它们由初始化

  • 在中添加MockitoAnnotations.initMocks(this);行设置方法

     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
     }
    
  • 或者将@RunWith(MockitoJUnitRunner.class)注释添加到TestClass中。

您没有初始化captor对象,因此无法执行其capture()方法。在调用对象的方法之前,必须对其进行初始化。

如果您使用的是Junit 5 jupitor,而像@Spy@Captor和@Mock这样的注释不适合您,那么这是因为;RunWith"被删除,您现在需要使用"@ExtendWith";注释。

因此,使用@ExtendWith(MockitoExtension.class)而不是@RunWith(MockitoJUnitRunner.class)将为您带来好处,并且注释将按预期工作。

相关内容

  • 没有找到相关文章

最新更新