SpringBoot:使用spring-boot-test对web应用做单元测试时如何测试Filter?

对SpringBoot的Web应用做单元测试时,一般会使用spring-boot-test,pom.xml中会添加如下内容:

XML 复制代码
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
 			<scope>test</scope>
		</dependency>

代码举例如下:

java 复制代码
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:

java 复制代码
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;
	}

}
java 复制代码
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注册并初始化一下,代码如下:

java 复制代码
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();
	}
......
}
相关推荐
yz_aiks4 小时前
Spring AI 2.1 ChatMemory 已过时用什么替代:迁移到 Session Memory 实战(JDBC 存储与会话压缩)
java·spring boot·大模型·ai agent·spring ai
学长毕设5 小时前
基于SpringBoot的上门洗车服务系统设计与实现
java·spring boot·后端
jaysee-sjc11 小时前
【苍穹外卖】Day12:工作台数据看板与 Excel 报表导出
java·开发语言·数据库·spring boot·spring·微信·excel
小蒜学长12 小时前
基于 Spring Boot 的英语单词背诵系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端
CoderYanger12 小时前
Java EE 进阶:5. Spring IoC&DI(第一弹):Spring IoC
java·开发语言·spring boot·spring·面试·职场和发展·java-ee
xiaoye-duck13 小时前
《C++ 工具库实战》GTest 单元测试:断言、全局环境、局部夹具与底层原理
c++·单元测试·第三方库
FYKJ_201015 小时前
springboot高考志愿填报推荐系统14332-计算机课程设计、毕业设计
javascript·spring boot·python·架构·django·课程设计·高考
vipxieliang16 小时前
ValidX vs 正则表达式:可读性与维护性对比
java·spring boot
3378016 小时前
5分钟搞懂登录认证和授权框架Spring Security
java·spring boot
vipxieliang16 小时前
Spring Security 6.x 实战:认证、授权与 JWT 集成
java·spring boot