SpringBoot:使用spring-boot-test对web应用做单元测试时如何测试Filter?
对SpringBoot的Web应用做单元测试时,一般会使用spring-boot-test,pom.xml中会添加如下内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
代码举例如下:
import static org.junit.jupiter.api.Assertions.assertEquals;
import javax.annotation.Resource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.test.protobuf.App;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class WebAppTester {
@Resource
private WebApplicationContext ctx = null;
private MockMvc mockMvc = null;
@Before
public void setupMockMvc() throws Exception {
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(ctx);
this.mockMvc = builder.build();
}
@Test
public void test01() throws Exception {
String result = doHttpAsyncTest(mockMvc, "/admin/health", "", null);
assertEquals("ok", result);
}
public String doHttpAsyncTest(MockMvc mockMvc, String uri, String httpBody, HttpHeaders httpHeaders)
throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(uri)
.contentType(MediaType.APPLICATION_JSON);
if (httpHeaders != null) {
builder.headers(httpHeaders);
}
MvcResult result = mockMvc.perform(builder.content(httpBody)).andReturn();
String httpRespBody = mockMvc.perform(MockMvcRequestBuilders.asyncDispatch(result))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON)).andReturn()
.getResponse().getContentAsString();
return httpRespBody;
}
}
如果应用中以如下方式添加了Filter的话,使用以上代码无法测试这些Filter:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestFilter implements Filter {
private String checkUrl = "/";
@Override
public void init(FilterConfig config) throws ServletException {
String checkUrl = config.getInitParameter("checkUrl");
if (checkUrl != null) {
this.checkUrl = checkUrl;
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpReqt = (HttpServletRequest) request;
String reqtUrl = httpReqt.getRequestURI();
if (!reqtUrl.startsWith(checkUrl)) {
chain.doFilter(request, response);
return;
}
HttpServletResponse httpResp = (HttpServletResponse) response;
httpResp.setStatus(200);
httpResp.setContentType("text/plain");
httpResp.getWriter().write("ok");
return;
}
}
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterRegistrationConfig {
public FilterRegistrationBean<TestFilter> testFilter() {
FilterRegistrationBean<TestFilter> reg = new FilterRegistrationBean<TestFilter>();
reg.setFilter(new TestFilter());
reg.addInitParameter("checkUrl", "/admin/");
reg.setName("TestFilter");
return reg;
}
}
如果想把这些Filter也测试到,需要在setupMockMvc方法中将Filter注册并初始化一下,代码如下:
import com.test.protobuf.App;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class WebAppTester {
@Resource
private WebApplicationContext ctx = null;
private MockMvc mockMvc = null;
@Resource
private FilterRegistrationBean<?>[] filterRegistrationBean = null;
@Before
public void setupMockMvc() throws Exception {
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(ctx);
for (FilterRegistrationBean<?> bean : filterRegistrationBean) {
MockFilterConfig filterConfig = new MockFilterConfig();
for (Entry<String, String> params : bean.getInitParameters().entrySet()) {
filterConfig.addInitParameter(params.getKey(), params.getValue());
}
Filter filter = bean.getFilter();
filter.init(filterConfig);
builder.addFilter(filter, bean.getUrlPatterns().toArray(new String[0]));
}
this.mockMvc = builder.build();
}
......
}