启动应用测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:consumer-test.xml"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
https://www.cnblogs.com/bihanghang/p/10023759.html
https://blog.csdn.net/u012260238/article/details/87462366
mock启动应用mock测试在class上面添加如下即可:
@RunWith(MockitoJUnitRunner.Silent.class)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringJUnitConfig(Application.class)
@TestPropertySource(locations = "classpath:application.properties")
@Slf4j
public class CalculatorTest {
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象
}
@Test
public void calculate() {
assertEquals(3, new Calculator().calculate("1 + 2"));
assertEquals(3, new Calculator().calculate("1 + 2 + 3"));
}
}
参数说明:
@SpringJUnitConfig(Application.class) 配置Spring中的测试环境
@BeforeClass 全局只会执行一次,而且是第一个运行
@Before 在测试方法运行之前运行
@Test 测试方法
@After 在测试方法运行之后允许
@AfterClass 全局只会执行一次,而且是最后一个运行
@Ignore 忽略此方法
@ConsumerLocations("consumer.xml")在dubbo单元测试中用到,配置消费者xml
@TestPropertySource(locations = "classpath:application.properties")配置xml配置文件
@RunWith(SpringJUnit4ClassRunner.class) 让测试在Spring容器环境下执行
@ContextConfiguration(Locations="../*.xml") 用于指定配置文件所在的位置
@RunWith 使用RunWith注解改变JUnit的默认执行类,并实现自已的Listener在平时的单元测试,如果不使用RunWith注解,那么JUnit将会采用默认的执行类Suite执行。
@ContextConfiguration 可以通过该属性手工指定 Spring 配置文件所在的位置,可以指定一个或多个 Spring 配置文件。
以上就是我们的单元测试,需要遵循一下规则:
1、每一个测试方法上使用@Test进行修饰
2、每一个测试方法必须使用public void 进行修饰
3、每一个测试方法不能携带参数
4、测试代码和源代码在两个不同的项目路径下
5、测试类的包应该和被测试类保持一致
6、测试单元中的每个方法必须可以独立测试
3、mock
什么是mock
单元测试:设置测试数据,设定预期结果,验证结果。mock就是创建某类型的虚拟对象,进行模拟操作。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!--表示开发的时候引入,发布的时候不会加载此包 -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<configuration>
<!-- 是否跳过测试 -->
<skipTests>false</skipTests>
<!-- 排除测试类 -->
<excludes>
<exclude>**/Base*</exclude>
</excludes>
</configuration>
以下是用例:
public class PersonServiceTest {
@Mock
private PersonDao personDAO; // 模拟对象
private PersonService personService; // 被测类
public PersonServiceTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
// 在@Test标注的测试方法之前运行
@Before
public void setUp() throws Exception {
// 初始化测试用例类中由Mockito的注解标注的所有模拟对象
MockitoAnnotations.initMocks(this);
// 用模拟对象创建被测类对象
personService = new PersonService(personDAO);
}
//@Ater是在每个测试方法运行完毕后均执行一次
@After
public void tearDown() {
}
@Test
public void shouldUpdatePersonName() {
Person person = new Person(1, "Phillip");
// 设置模拟对象的返回预期值
when(personDAO.fetchPerson(1)).thenReturn(person);
// 执行测试
boolean updated = personService.update(1, "David");
// 验证更新是否成功
assertTrue(updated);
// 验证模拟对象的fetchPerson(1)方法是否被调用了一次
verify(personDAO).fetchPerson(1);
// 得到一个抓取器
ArgumentCaptor<Person> personCaptor = ArgumentCaptor.forClass(Person.class);
// 验证模拟对象的update()是否被调用一次,并抓取调用时传入的参数值
verify(personDAO).update(personCaptor.capture());
// 获取抓取到的参数值
Person updatePerson = personCaptor.getValue();
// 验证调用时的参数值
assertEquals("David", updatePerson.getPersonName());
// asserts that during the test, there are no other calls to the mock object.
// 检查模拟对象上是否还有未验证的交互
verifyNoMoreInteractions(personDAO);
}
@Test
public void shouldNotUpdateIfPersonNotFound() {
// 设置模拟对象的返回预期值
when(personDAO.fetchPerson(1)).thenReturn(null);
// 执行测试
boolean updated = personService.update(1, "David");
// 验证更新是否失败
assertFalse(updated);
// 验证模拟对象的fetchPerson(1)方法是否被调用了一次
verify(personDAO).fetchPerson(1);
// 验证模拟对象是否没有发生任何交互
verifyZeroInteractions(personDAO);
// 检查模拟对象上是否还有未验证的交互
verifyNoMoreInteractions(personDAO);
}
/**
* Test of update method, of class PersonService.
*/
@Test
public void testUpdate() {
System.out.println("update");
Integer personId = null;
String name = "Phillip";
PersonService instance = new PersonService(new PersonDao() {
@Override
public Person fetchPerson(Integer personID) {
System.out.println("Not supported yet.");
return null;
}
@Override
public void update(Person person) {
System.out.println("Not supported yet.");
}
});
boolean expResult = false;
boolean result = instance.update(personId, name);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
}
也可只使用
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class NativeTest {}
用例如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class NativeTest {
//需要模拟的对象
@Mock
UserServiceImpl userService;
//需要测试的类
@InjectMocks
LoginServiceImpl loginServiceImpl
@Test
public void shouldNotUpdateIfPersonNotFound() {
// 设置模拟对象的返回预期值
when(userService.fetchPerson(1)).thenReturn(null);
// 执行测试
boolean updated = oginServiceImpl.login(1, "David");
// 验证更新是否失败
assertFalse(updated);
// 验证模拟对象的fetchPerson(1)方法是否被调用了一次
verify(personDAO).fetchPerson(1);
// 验证模拟对象是否没有发生任何交互
verifyZeroInteractions(personDAO);
// 检查模拟对象上是否还有未验证的交互
verifyNoMoreInteractions(personDAO);
// 检查模拟对象上是否没有调用
verify(userService, never()).fetchPerson(any());
verify(userService, times(2)).getUserInfoByMobile(any());
verify(userService, never()).fetchPerson(any());
//调到时不进行处理,只有返回void的方法可用
doNothing().when(jmqProducer).sendMessage(any(),anyString(),anyString());
Mockito.when(userService.cfetchPerson(anyString(), any())).thenReturn(new User());
verify(jmqProducer, never()).sendMessage(any(),anyString(),anyString());//never代表方法调用0次
//调用两次
verify(oginServiceImpl, times(2)).login(anyString(),any());
Assert.assertEquals(userDto.getName(),1);
//异常测试
try {
oginServiceImpl.login(null);
} catch (Exception e) {
Assert.assertTrue(e instanceof BusinessException);
}
thrown.expect(BusinessException.class);
}
}
当单元测试中需要moke掉类中@Value注解时可用
ReflectionTestUtils.setField(userServiceImpl, "sourceType", "es");
在@Before中添加其中userServiceImpl为@InjectMocks需要测试的类,sourceType为@Value的参数es为moke的值。
安装TestMe插件之后再类上面点击alt+insert键可快速生成mock的test方法
可在测试类上面添加
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:consumer-test.xml"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Slf4j
或者使用如下也可以用如下完整实例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class CollectOptConsumerTest {
@Resource
private CollectOptConsumer collectOptConsumer;
@Test
public void execute() {
String text = "{\"operateTime\":1615026212069}";
collectOptConsumer.execute(text);
}
}
@SpringBootApplication
@PropertySource(value = {
"classpath:META-INF/config/producer.properties",
"classpath:META-INF/config/jconsumer.properties",
"classpath:META-INF/config/message.properties",
"classpath:META-INF/config/jdbcp.properties"
})
@ImportResource(value = {
"classpath:META-INF/spring/jmq-producer.xml",
"classpath:META-INF/spring/jmq-consumer.xml",
"classpath:META-INF/spring/spring-consumer.xml",
"classpath:META-INF/spring/applicationContext.xml",
"classpath:META-INF/spring/spring.xml",
"classpath:META-INF/spring/spring-es.xml",
"classpath:META-INF/spring/single-datasource-test.xml",
"classpath:META-INF/spring/spring-config.xml",
"classpath:META-INF/spring/spring-jss.xml",
// "classpath:META-INF/spring/sharding-datasource.xml",
"classpath:META-INF/spring/spring-es.xml"
})
@MapperScan({"com.test.activity.recybag.dao","com.test.activity.dao.*"})
public class TestApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TestApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}