spring boot test MockBean

使用spring boot , MockBean

 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = Application.class)
 public class DalListTest {
    @MockBean
    private  XxxService xxxService;
}

classes指定主程序的入口

@MockBean可以在代替实际的Bean, 用来解决一些初始化问题, 比如用例启动不了。不需要在测试类中使用@Configuration, @Bean

默认查找bean的package和主程序入口package相同

mock maven依赖

``` org.mockito mockito-core ${mockito.version} ```
@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版本稍有区别
@ActiveProfiles("test,local")
@RunWith(SpringRunner.class)
@ImportAutoConfiguration(classes = {MybatisPlusAutoConfiguration.class, JdbcTemplateAutoConfiguration.class})
@JdbcTest
@WebAppConfiguration
public class ApiAddressDaoTest {

    @Autowired
    private ApiAddressDao apiAddressDao;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    public void test_queryList() {

        // 打桩  如果使用entityManager 会自动创建表
        jdbcTemplate.execute("create table ns_address (id int null, user_id int)");
        jdbcTemplate.execute("insert into ns_address values(11, 156)");
        
        // 验证
        List<AddressVo> addressVos = apiAddressDao.listAddress(156L);
        assertThat(addressVos).isNotEmpty();
    }

}
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)

spy()的作用

Mockito "spy" function, 
which wraps a real object with a mock object. 
All calls to the mock object get forwarded to the real object, except those you are trying to mock. 

然后才能用when(mockBean).doXXX()方法

为什么有的doThrow()是放在 when(aaaa).xxxx()前面?

因为xxx()方法的返回值是void, 这时不能用when.xxx().doThrow

final static field是可以使用反射修改的

修改 'modifiers'里的final标识位, 直接把final remove掉


static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }

新版本的mockito可以直接mockStatic(xxx.class)

final class mock时需要加上mockito-inline

<dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <version>5.2.0</version>
            <scope>test</scope>
        </dependency>

单元测试的优点和价值:

1.基准测试, 有对比, 可验证,建立修改的信心
2.文档作用
3.可重用 速度快 不用每次都找前端要参数

https://www.baeldung.com/mockito-annotations

posted @ 2018-07-20 13:46  funny_coding  阅读(1953)  评论(0编辑  收藏  举报
build beautiful things, share happiness