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