我们在项目中,经常要编写一个测试类XXXXXTest,其中一般会用到以下注解:
一、常用注解
1. @RunWith(PowerMockRunner.class)
JUnit将会调用@RunWith中指定的测试执行类而不是JUnit默认的执行类。
2.@PrepareForTest({ExampleTestServer.class})
2.1 当使用Mockito.whenNew方法时(下面的Mock测试),必须加此注解,此注解里写的类是需要mock的new对象代码所在的类。
2.2 当需要使用mock final、mock static方法、mock private方法、mock系统类的静态方法时,必须加此注解,此注解里写的分别是该方法所在的类。
3.@InjectMocks
创建一个实例,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中。
(通常在真正运行时,会使用@Autowired等方式完成自动注入。但是在单元测试中,没有启动spring框架,此时就需要@InjectMocks来完成依赖注入,@InjectMocks会将带有@Mock以及@Spy注解的对象注入到被测试的目标类中:
- 在进行单元测试时,不应初始化 Spring 上下文。因此,请@Autowired。
- 在进行集成测试时,应使用真正的依赖项。所以去掉Mock)
4.@Mock
@Mock:创建一个Mock。
5.@Test
被打上该注解的方法,表示为一个测试方法。
二、Mock测试
1.Stub打桩
Mockito 中 when().thenReturn(); 这种语法来定义对象方法和参数(输入),然后在 thenReturn 中指定结果(输出)。此过程称为 Stub 打桩 。一旦这个方法被 stub 了,就会一直返回这个 stub 的值。
Mockito.when(request.getParameter("csdn")).thenReturn("lirenji");
注意:
- 对于 static 和 final 方法, Mockito 无法对其 when(…).thenReturn(…) 操作。
- 当我们连续两次为同一个方法使用 stub 的时候,他只会只用最新的一次。
2.迭代打桩
第一次调用 i.next() 将返回 ”Hello”,第二次的调用会返回 ”World”。
// 方法一 (三个方法等价)
when(i.next()).thenReturn("Hello").thenReturn("World");
// 方法二
when(i.next()).thenReturn("Hello", "World");
// 方法三
when(i.next()).thenReturn("Hello"); when(i.next()).thenReturn("World");
3.抛出异常
//一般情况
when(i.next()).thenThrow(new RuntimeException());
// void 方法的
doThrow(new RuntimeException()).when(i).remove();
// 迭代风格 (第一次调用 remove 方法什么都不做,第二次调用抛出 RuntimeException 异常)
doNothing().doThrow(new RuntimeException()).when(i).remove();
4.Any
anyString()
匹配任何 String 参数,anyInt()
匹配任何 int 参数,anySet()
匹配任何 Set,any()
则意味着参数为任意值 any(User.class)
匹配任何 User类。
when(mockedList.get(anyInt())).thenReturn("element");
System.out.println(mockedList.get(999));// 此时打印是 element
System.out.println(mockedList.get(777));// 此时打印是 element
Example:
有如下代码段:
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
@Autowired
private YourRepository yourRepository;
public void doSomething() {
this.myRepository.doSomething();
}
}
测试类:
@RunWith(MockitoJUnitRunner.class)
@PrepareForTest(MyService.class)
public class UserServiceTest {
@InjectMocks
private MyService myService;
@Mock
private MyRepository myRepository;
@Mock
private YourRepository yourRepository;
@Test
public void testInjectMocks() {
System.out.println(myService.getMyRepository().getClass());
}
}