springboot junit测试
这边记录的不是怎么在springboot下作测试,而是最近在学习测试时遇到的一个有趣的问题。
啰嗦两句,一直觉得单元测试很重要,但我在以前的工作中发现很少有人重视,或者很少有人去写这个单元测试,其实单元测试也不难,关键得上手,慢慢就会有感觉,但说实话一开始不会写的话,需要有个样例,这样你去琢磨它,学着写2个应该很快就能上手。另外一点是从测试开始读别人项目的代码也不失为一个好办法,我最近在读别人代码时,想搞清楚它的多数据源是怎么做的,于是我就对Dao层做简单的测试调用。如下面第一个方法,看起来很简单,@TestExecutionListeners和RequestHeaderSettingTestExecutionListener 这个类请忽略,它正是为了解决我遇到的问题的。我遇到的问题是这样的,我只是简单的执行dao方法,但是底层在实际获取数据库连接时会选择一个数据源,上面也说了项目用了动态数据源,那么它在获取动态数据源时的一个算法是根据请求头里的标记(即我下面的示例header:yourHeader)的值决定去取哪个数据源的连接,让我纳闷的是我这执行的是dao方法,但是程序在执行(ServletRequestAttributes)RequestContextHolder.getRequestAttributes().getRequest()时,居然可以拿到这个请求,这是什么情况,这个我理解是启用的springboottest,创建了请求上下文。我现在要做的就是在请求头中传入我想调用的数据源key。因此使用@TestExecutionListeners和自定义类RequestHeaderSettingTestExecutionListener可以实现这一点。
@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)//添加这行下面的xxDao才会注入
@TestExecutionListeners(
listeners = RequestHeaderSettingTestExecutionListener.class, //这是自定义的
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)//会自动合并自定义的监听器和默认的监听器。防止冲突导致xxDao无法注入
public class xxDaoTest {
@Autowired
XxDao xxDao;
@Test
public void testGetActionByName() {
Assert.assertNotNull("无记录", idsDao.getActionByName("test"));
}
}
public class RequestHeaderSettingTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
// 在测试方法执行前设置模拟的请求头
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("yourHeader","itsValue");//这边设置后续要通过(ServletRequestAttributes)RequestContextHolder.getRequestAttributes().getRequest()获取的header
ServletRequestAttributes attributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(attributes);
}
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
// 清理请求上下文,避免影响其他测试
RequestContextHolder.resetRequestAttributes();
}
}