利用Mockito模拟DB
最编程
2024-01-03 11:10:43
...
前两篇文章的主要内容是:为了给执行测试,如何建立数据库表和导入初始数据。这里我们将学习如何利用Mockito框架和一些注解模拟(mock)Repository实例,从而使得测试用例不依赖外部的数据库服务。
我们需要创建一个Spring Boot配置类,在该类中定义用于测试的Spring Bean;我们通过注解指示Spring Boot何时加载测试配置类以及何时执行该类中的代码。在改配置类中,我们将使用Mockito框架创建一些带预定义方法的mock对象,Spring Boot在执行测试用例之前会将这些对象织入。
How Do
- 首先创建一个注解用于标识仅用于测试的配置类,可以按照如下方法修改BookPubApplication类。可以看出,关键语句@ComponentScan(excludeFilters = @ComponentScan.Filter(UsedForTesting.class))表示:程序正式运行时不扫描@UsedForTesting修饰的类。
@Configuration@EnableAutoConfiguration@ComponentScan(excludeFilters = @ComponentScan.Filter(UsedForTesting.class))
@EnableSchedulingpublicclassBookPubApplication{
publicstaticvoidmain(String[] args){
SpringApplication.run(BookPubApplication.class, args);
}
@Beanpublic StartupRunner schedulerRunner(){
returnnew StartupRunner();
}
}
@interface UsedForTesting {}
- 在src/test/java/com/test/bookpub目录下创建TestMockBeansConfig文件,内容是:
packagecom.test.bookpub;
importcom.test.bookpub.repository.PublisherRepository;
importorg.mockito.Mockito;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.context.annotation.Primary;
@Configuration
@UsedForTesting
public class TestMockBeansConfig {
@Bean
@Primary
public PublisherRepository createMockPublisherRepository() {
returnMockito.mock(PublisherRepository.class);
}
}
- 新建一个测试类——PublisherRepositoryTests,主要是因为BookPubApplicationTest中的内容太多太乱了(在实际项目中我们会严格限制每个测试类中的内容)。
packagecom.test.bookpub;
importcom.test.bookpub.repository.PublisherRepository;
importorg.junit.After;importorg.junit.Before;importorg.junit.Test;
importorg.junit.runner.RunWith;importorg.mockito.Mockito;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.IntegrationTest;
importorg.springframework.boot.test.SpringApplicationConfiguration;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
importstaticorg.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {
BookPubApplication.class,
TestMockBeansConfig.class
})
@IntegrationTest
public class PublisherRepositoryTests {
@Autowired
private PublisherRepository repository;
@Before
public void setupPublisherRepositoryMock() {
Mockito.when(repository.count())
.thenReturn(1L);
}
@Test
public void publishersExist() {
assertEquals(1, repository.count());
}
@After
public void resetPublisherRepositoryMock() {
Mockito.reset(repository);
}
}
分析
OK,分析下刚刚发生了什么。首先,我们从对BookPubApplication.java的修改开始:
- @SpringBootApplication被三个注解替换:@Configuration, @EnableAutoConfiguration和@ComponentScan(excludeFilters = @ComponentScan.Filter(UsedForTesting.class)),这么做的原因是可以给@ComponentScan注解增加excludeFilters属性,通过这个属性,我们提示Spring Boot在正式运行时忽略被@UsedForTesting修饰的类。
- @UsedForTesting注解定义在BookPubApplication.java文件中,用于修饰TestMockBeansConfig类。
接下来看看在TestMockBeansConfig中的操作,
- @Configuration注解说明这是一个配置类,该类含有应用程序上下文,如果被其他配置文件引入,则该类中定义的Spring Bean应该加入到已经创建的应用上下文。
- 修饰createMOckPublisherRepository方法的注解@Primary表示:如果在织入的时候发现有多个PublisherRepository的Spring Bean,则让Spring Boot优先使用该方法返回的Spring Bean。在应用程序启动时,Spring Boot根据@RepositoryRestResource注解,已经生成一个PublisherRepository的实例,但是这里我们希望应用程序不使用这个真实的实例,而使用Mockito框架模拟出的PublisherRepository实例。
最后看下我们的测试用例,主要关注setupPublisherRepositoryMock方法和resetPublisherRepositoryMock方法:
setupPublisherRepositoryMock方法被@Before注解修饰,表示在测试用例运行之前被调用,在这个方法中我们配置了mock对象的行为:如果收到repository.count()调用,则返回1。Mockito框架提供了很多DSL形式的语句,可以用于定义这些容易理解的规则。
resetPublisherRepositoryMock方法被@After注解修饰,在测试用例执行过后调用,用于清楚之前对repository的设置。
推荐阅读
-
一篇教你模拟的文章(Mockito 和 PowerMock 双剑合璧)
-
Unity 利用物理引擎进行多旋翼无人机飞行模拟
-
Mockito 3.8 如何模拟静态方法(如何模拟 PageHelper)
-
利用 Lammps 模拟金刚石刀具切割金属基材
-
Hi3559AV100 NNIE 开发 (5) mobilefacenet.wk 利用 CNN_convert_bin_and_print_featuremap.py 模拟成功的量化和比较过程 输出中间层数据
-
利用定向耦合器方法测量 5.8G 天线反射系数(HFSS-ADS 联合模拟)
-
很好地利用了轮盘 turn.js 来实现翻书的模拟效果
-
使用 Mockito 模拟静态方法的教程
-
利用反射等距超曲面进行模拟光学计算
-
实战教学:利用three.js在WebGL中创建酷炫3D效果——打造6讲实例,包括3D虚拟消防演练、大型3D建筑、数字化孪生火警模拟、可视化方案(第18课变体)与3D智慧园区、大屏及楼宇等全方位三维呈现与BIM管理系统的Web版应用(第6课)