搭建单元测试以及遇到的问题
目标
搭建单元测试,希望能mock部分方法,以及数据库的加载
pom
<!-- add unit test support -->
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.38</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.wizard.component</groupId>
<artifactId>data-uploader</artifactId>
<version>0.0.3</version>
<scope>test</scope>
</dependency>
<!-- JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version> 4.12</version>
</dependency>
单数据源测试基类
所有单元测试类继承下面的类
@RunWith(SpringRunner.class)
//properties 如果没有开发环境没有多环境不需要这个参数
@SpringBootTest(classes = YourApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.MOCK,
properties = {)
@Transactional
//数据回滚,有构造数据的可重复跑,数据插入后,执行完单测,回滚数据
@Rollback
public class BaseTest {
private static Logger logger = LoggerFactory.getLogger(BaseTest.class);
@Autowired
protected JdbcTemplate jdbcTemplate;
@Autowired
protected SqlSessionFactory sqlSessionFactory;
@Rule
public ExpectedException exception = ExpectedException.none();
/**
* 同事封装的加载数据工具类
* 原理:加载读取csv的数据根据案例名,通过jdbctemplate来插入数据
*准备db测试数据, 根据案例名 扫描table csv插入DB tables空全量扫描
* @param caseFlag
* @param tables
*
*
*
*/
protected void loadTestData(String caseName, String... tables) {
new DataUploader(jdbcTemplate).uploadCsvByIndex("src/test/resources/testdata/_index.txt", caseName, tables);
}
}
编写一个单元测试
/**
** 提前构造数据
**/
public class YourServiceTest extends BaseTest {
@Autowired
private YourMapper YourMapper;
@Test
@Rollback
@Transactional
public void getYourTest() {
//插入数据
loadTestData("YourServiceTest.getYourTest");
//查询插入的是否写入成功
Your your = YourMapper.getOne(-1000L);
Assert.assertTrue(-1000L == your.getProperty());
}
}
/**
** mock方法
**/
public class yourServiceTest extends BaseTest {
@Autowired
private YourService yourService;
@Test
public void yourfunctionTest() {
YourService = mock(YourService.class);
Response<Boolean> response = new Response<>();
response.setData(true);
response.setMsg("成功拉");
//mock方法返回值
when(yourService.youfunction(anyLong())).thenReturn(response);
Response<Boolean> response1 = yourService.youfunction(anyLong());
Assert.assertTrue(response1.getData());
}
}
多数据源构造数据不回滚的处理方法
主要要指定基类事务使用的数据源的管理器
@RunWith(SpringRunner.class)
//properties 如果没有开发环境没有多环境不需要这个参数
@SpringBootTest(classes = YourApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.MOCK,
properties = {"spring.profiles.active=指定你的环境"})
//多数据源需要指定,事务生效的管理器
@Transactional("OneTransactionManager")
//数据回滚,有构造数据的可重复跑,数据插入后,执行完单测,回滚数据
@Rollback
public class BaseTest {
private static Logger logger = LoggerFactory.getLogger(BaseTest.class);
@Autowired
protected JdbcTemplate jdbcTemplate;
//指定使用的
@Autowired
@Qualifier("OneJdbcTemplate")
protected JdbcTemplate OneJdbcTemplate;
@Autowired
// @Qualifier("OneSqlSessionFactory")
protected SqlSessionFactory sqlSessionFactory;
@Rule
public ExpectedException exception = ExpectedException.none();
/**
* 同事封装的加载数据工具类
* 原理:加载读取csv的数据根据案例名,通过jdbctemplate来插入数据
*准备db测试数据, 根据案例名 扫描table csv插入DB tables空全量扫描
* @param caseFlag
* @param tables
*
*
*
*/
protected void loadTestData(String caseName, String... tables) {
new DataUploader(OneJdbcTemplate).uploadCsvByIndex("src/test/resources/testdata/_index.txt", caseName, tables);
}
}
获取数据源的jdbctemplate
@Configuration
//指定配置数据源
@ConfigurationProperties(prefix = "spring.datasource.one")
//指定扫描的包
@MapperScan(basePackages = "指定你扫描的包", sqlSessionTemplateRef = "OneSqlSessionTemplate")
public class OneConfig {
private String url;
private String driverClassName;
private String username;
private String password;
@Bean(name = "initDataSource")
public DruidDataSource initDataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(url);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
return datasource;
}
@Bean(name = "OneDataSource")
public DataSource decryptOneDataSource(@Qualifier("initDataSource") DruidDataSource dataSource) {
CommonLogUtil.info("OneConfig decryptOneDataSource start");
return new TransactionAwareDataSourceProxy(dataSource);
}
@Bean(name = "OneSqlSessionFactory")
public SqlSessionFactory OneSqlSessionFactory(@Qualifier("OneDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/One/*.xml"));
bean.getObject().getConfiguration().addInterceptor(new PrintSqlIdIntoDruidLogInterceptor());
return bean.getObject();
}
@Bean(name = "OneTransactionManager")
public DataSourceTransactionManager OneTransactionManager(@Qualifier("OneDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "OneSqlSessionTemplate")
public SqlSessionTemplate OneSqlSessionTemplate(@Qualifier("OneSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
//创建数据源的jdbcTemplate
@Bean(name ="OneJdbcTemplate")
public JdbcTemplate OneJdbcTemplate(@Qualifier("OneDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public Slf4jLogFilter logFilter(){
Slf4jLogBoostFilter filter = new Slf4jLogBoostFilter();
filter.setStatementExecutableSqlLogEnable(true);
filter.setResultSetLogEnabled(false);
filter.setConnectionLogEnabled(false);
filter.setStatementParameterClearLogEnable(false);
filter.setStatementCreateAfterLogEnabled(false);
filter.setStatementCloseAfterLogEnabled(false);
filter.setStatementParameterSetLogEnabled(false);
filter.setStatementPrepareAfterLogEnabled(false);
filter.setStatementExecuteQueryAfterLogEnabled(false);
filter.setStatementSqlPrettyFormat(false);
filter.setStatementExecuteUpdateAfterLogEnabled(false);
filter.setStatementExecuteQueryAfterLogEnabled(false);
filter.setStatementLogEnabled(false);
return filter;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}