java项目的测试相关 springboot Junit

之前的编写代码的时候,由于时间限制等原因,一直觉得写单元测试是额外的工作量,也不爱写或者是开发完成之后再后补,有应付了事的嫌疑,没有做出单元测试的真是意义。但是这样往往会在修改完一个问题之后,可能引起其他问题而不自知。

所以单元测试还是有必要的。然后最近就研究了一下,应该用何种方式,什么工具去做测试,网上也找了一堆资料,基本上都是spock(groovy编写,还未使用过,后续试试),还有说要借鉴appfuse的测试思想去做(自行百度吧),什么DBUnit ,JUnit等等吧。

这些只是自己初略了解了下,但是具体有些也清楚怎么用,鉴于自己的需求,最后选择了JUnit,mockMvc,h2 database

自身系统情况:

使用Springboot + mybatis + mySql 实现的web项目

大致的思路是把三层都可以进行单元测试

1、dao

2、service

3、controller

1、dao

SpringBoot 整合H2测试Dao可以查看这篇日志: http://blog.csdn.net/mn960mn/article/details/54644908

因为 h2的配置中初始话表数据的时候,如果直接是使用INIT=RUNSCRIPT FROM 这种引入插入数据的时候,但是不知道为什么 数据被插入了10遍,所以没办法只能更换方式,使用spring.datasource.data 进行初始化了。

## h2 database
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test;MODE=MYSQL;
##INIT=RUNSCRIPT FROM 'classpath:sql/init_table.sql'\\;RUNSCRIPT FROM 'classpath:sql/init_data.sql'  ## this i don't konw why it insert 10 datas
#spring.datasource.url=jdbc:h2:file:~/.h2/db_users;MODE=MYSQL;AUTO_SERVER=TRUE;   ## file save to local
spring.datasource.username=
spring.datasource.password=
spring.datasource.schema=classpath:sql/init_table.sql
spring.datasource.data=classpath:sql/init_data.sql
 

2、service 

测试service也比较简单,只需要执行service的扫描包就可以了。这样在测试类中就可以使用相应的bean了。

@Configuration
@ComponentScan(basePackages = {"com.test.service.**"})
public class ServiceConfiguration {

}
 

 3、controller

这个是在测试的时候问题比较多的地方,其实原本如果使用的是正常的mysql数据库(跟平时开发用的一个)也还好,但是为了实现单体测试和开发那个数据库分离,添加的这个H2数据库就出现问题了。

原因是我们自己重新定义了datasource 

@Configuration
@MapperScan({ "com.xxx.**.mapper"})
@ComponentScan({ "com.xxx.datasource"})
@Slf4j
public class MapperAdminConfiguration {
    @Bean
    @ConfigurationProperties(prefix="my.jdbc")
    public MyDataSource dataSource() {
       return (MyDataSource ) DataSourceBuilder.create()
                                                    .type(MyDataSource.class).build();
    }
}

  注意:  以上代码有一些自身的逻辑,所以直接修改配置变为h2应该是不好用的,因为是后加的Test,所以不会动原来的代码

正常在Test文件中,指定 @SpringBootTest(classes={Application.class})就可以把需要的内容都进行加载初始化,但是由于通过@bean形式配置了datasource,那么加载时就会把配置文件中配置的默认的datasource进行覆盖,而去使用my.jdbc开头的配置信息。就没办法使用H2数据库了.

那么就想到了直接使用@SpringBootTest(classes={Application.class})这个。而是只引入自己需要的,就像Dao测试那样,然后自己就建立了一个

@Configuration
@ComponentScan(basePackages = {"com.xxxx.**")
public class ServiceConfiguration {

}
 
@RunWith(SpringRunner.class)  
/** 
 *  这里指定的classes是可选的。如果不指定classes,则spring boot会启动整个spring容器,很慢(比如说会执行一些初始化,ApplicationRunner、CommandLineRunner等等)。不推荐 
 *  指定的话,就只会初始化指定的bean,速度快,推荐 
 */  
@SpringBootTest(classes={DataSourceAutoConfiguration.class, MybatisAutoConfiguration.class, 
        MapperConfiguration.class,ServiceConfiguration.class})
@WebAppConfiguration
public class PlatformControllerTest {  
    
    MockMvc mvc;  
    
    @Autowired  
    WebApplicationContext webApplicationContext;  
    
    @Before  
    public void setUp() {  
        mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();  
    }  
     
    @Test  
    public void list() throws Exception {  
        String uri = "/admin/admin/platform/list/all";  
        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(uri).accept(MediaType.APPLICATION_JSON)).andReturn();  
        int status = mvcResult.getResponse().getStatus();  
        String result = mvcResult.getResponse().getContentAsString();  
        Assert.assertTrue("Wrong,status not 200 ,is " + status, status == 200);  
        Assert.assertFalse("Wrong,status not 200 ,is " + status, status != 200);  
    }  
    
    
    
    //@Test   
    public void testList(){
        RestTemplate restTemplate = new RestTemplate();//测试http请求的
        String url = "http://localhost:8080/admin/admin/platform/list/all";
        Map map = new HashMap<>();
        String result = restTemplate.getForObject(url, String.class, map);
        System.out.print(result+"=========");
    }
    
}
 

但是问题出现了,因为返回的是对象,在list()方法返回的http状态一直是406,原因应该是在messageConverter的时候没有转,正常情况下SpringBoot是有一个WebMvcAutoConfiguration ,里边会添加上一些默认的HttpMessageConverters,自动进行转换的,但是现在不好用了,说明这个没有进行加载。

为什么使用 @SpringBootTest(classes={Application.class}) 可以加载进来,具体是怎么加载我也看不明白,无奈只能先看看Application类都有哪些东西吧

@SpringBootApplication
@EnableAspectJAutoProxy
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

}
 

相关推荐