编写Servlet测试用例时,如何用Mockito初始化ServletConfig变量?
你遇到的核心问题是:虽然Mock了ServletConfig,但没把这个Mock实例关联到AddUsers Servlet对象上,导致Servlet里调用getServletConfig()时返回null,所有初始化参数自然也取不到。
解决方案:关联Mock的ServletConfig到Servlet实例
有两种简单的方法可以搞定这个问题:
方法1:手动调用setServletConfig()方法
GenericServlet(Servlet的父类)提供了setServletConfig()方法,你可以在测试中直接把Mock的ServletConfig绑定到Servlet实例上:
@Test public void test() throws Exception { // ... 你的其他测试准备代码:构造请求内容、设置Mock的init参数等 ... // 创建Servlet实例并绑定Mock的ServletConfig AddUsers addUsersServlet = new AddUsers(); addUsersServlet.setServletConfig(sg); // 关键步骤:把Mock的sg关联到Servlet // 调用service方法 addUsersServlet.service(request, response); // ... 你的断言和验证逻辑 ... }
方法2:使用@InjectMocks自动注入
借助Mockito的@InjectMocks注解,让它自动把Mock的ServletConfig注入到Servlet实例中,代码更简洁:
首先调整测试类的字段声明:
@Mock HttpServletRequest request; @Mock HttpServletResponse response; @Mock HttpSession session; @Mock RequestDispatcher rd; @Mock ServletOutputStream servletOut; @Mock ServletConfig sg; @InjectMocks // 让Mockito自动将所有Mock注入到这个Servlet实例中 private AddUsers addUsersServlet;
然后修正setUp方法的注解(注意:@BeforeClass是类级别的一次性初始化,换成@Before保证每个测试方法前都能正确初始化Mocks):
@Before // 替换原来的@BeforeClass public void setUp() throws Exception { MockitoAnnotations.initMocks(this); }
最后在测试方法中直接使用注入好的Servlet实例:
@Test public void test() throws Exception { // ... 你的其他测试准备代码 ... // 直接调用已注入Mock的Servlet实例的service方法 addUsersServlet.service(request, response); // ... 你的断言和验证逻辑 ... }
为什么原来的代码不生效?
当你直接new AddUsers()时,这个Servlet实例的内部ServletConfig字段是null(正常场景下是由Servlet容器初始化并设置的)。你虽然Mock了ServletConfig,但没把它和Servlet实例绑定,所以getServletConfig()自然返回null,所有getInitParameter()调用也就都返回null了。
上面两种方法都是把Mock的ServletConfig设置到Servlet实例的内部字段中,这样getServletConfig()就会返回你Mock的对象,初始化参数就能正常获取到了。
内容的提问来源于stack exchange,提问作者Jaydeep Bobade

