使用spring boot , MockBean
1 @RunWith(SpringRunner.class)
2 @SpringBootTest(classes = Application.class)
3 public class DalListTest {
4
5 @MockBean
6 private XxxService xxxService;
7
8 }
classes指定主程序的入口
@MockBean可以在代替实际的Bean, 用来解决一些初始化问题, 比如用例启动不了。不需要在测试类中使用@Configuration, @Bean
默认查找bean的package和主程序入口package相同
mock maven依赖
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>${mockito.version}</version> </dependency>
@SpringBootTest是用在集成测试阶段的,单元测试中不要用这个, 而且单元测试的代码需要和集成测试的代码分开
TDD实践中是先做单元测试,然后实现代码, 再做集成测试
单元测试 是先建立验证目标, 然后实现具体代码。
单元测试时 只需要@RunWith(SpringRunner.class),不要@SpringBootTest
比如只验证controller时, service层的bean是mock打桩, 配合@WebMvcTest就够了
只验证service时, 使用@RunasJunit就行, mock mapper bean
只验证orm时, 使用@JdbcTest,要导入MybatisAutoConfig, 默认不会自动加载autoConfig类。
此时也是要初始化DataSource, sqlSessionFactory ..., 只不过@JdbcTest帮我们初始化了,不用再手动new相关对象
@JdbcTest会自动使用h2数据库, 如果想使用xml中的jdbc路径,需要修改配置spring.test.database.replace=none, springboot1,2版本稍有区别
1 @ActiveProfiles("test,local") 2 @RunWith(SpringRunner.class) 3 @ImportAutoConfiguration(classes = {MybatisPlusAutoConfiguration.class, JdbcTemplateAutoConfiguration.class}) 4 @JdbcTest 5 @WebAppConfiguration 6 public class ApiAddressDaoTest { 7 8 @Autowired 9 private ApiAddressDao apiAddressDao; 10 11 @Autowired 12 private JdbcTemplate jdbcTemplate; 13 14 @Test 15 public void test_queryList() { 16 17 // 打桩 如果使用entityManager 会自动创建表 18 jdbcTemplate.execute("create table ns_address (id int null, user_id int)"); 19 jdbcTemplate.execute("insert into ns_address values(11, 156)"); 20 21 // 验证 22 List<AddressVo> addressVos = apiAddressDao.listAddress(156L); 23 assertThat(addressVos).isNotEmpty(); 24 } 25 26 }
https://www.baeldung.com/spring-boot-testing
https://github.com/mbhave/tdd-with-spring-boot
@TestPropertySource(xxx.properties) 会覆盖application.properties中的配置
@DataJpaTest(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class))
相当于ComponentScan中的excludeFilters, 用于排除一些不想初始化的bean, 可基于annotation、 ASPECTJ、REGEX等过滤
excludeAutoConfiguration属性可以排除一些AutoConfiguration类(有些autoconfig初始化很麻烦,unit test又用不到)
与集成测试的区别是生成的ApplicationContext类型不同,自动扫描的bean不同, 但都会生成BeanFactory,
作为应用跑起来时是WebApplicationContext, 作为测试类跑起来时TestA
如果应用主类包含ComponentScan, 会影响bean的加载,@DataJpaTest可能会加载service bean, 此时需要ConditionalOnXXXX排除主类的ComponentScan
MockitoAnnotations.initMocks(this)
单元测试的优点和价值:
1. 基准测试, 有对比, 可验证,建立修改的信心
2. 文档作用
3. 可重用 速度快 不用每次都找前端要参数