一、区别
1.说明
-
@Mock 模拟对象的所有方法都不会调用其实际实现,而是返回默认值或根据定义的行为返回值,相当于 Mockito.mock
-
@Spy 间谍对象是一个真实的对象,但你可以选择性地模拟其中的一些方法,相当于 Mockito.spy
-
@InjectMocks 用于创建一个主要的对象(通常是要测试的对象),并且自动注入所有使用 @Mock 或 @Spy 注解的依赖项
2.模拟
-
模拟有返回值的方法:Mockito.when(methodCall).thenReturn(value)
-
模拟无返回值的方法:Mockito.doNothing().when(mock).method()
-
模拟有返回值的静态方法:mockedStatic.when(verification).thenReturn(value)
-
模拟无返回值的静态方法:mockedStatic.when(verification).thenAnswer(invocation -> null)
二、示例
1.pom
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>
2.代码
MyDao1.java
public interface MyDao1 {
Integer count11(Integer i);
Integer count12(Integer i);
void test11();
}
public class MyDao1Impl implements MyDao1 {
@Override
public Integer count11(Integer i) {
return i;
}
@Override
public Integer count12(Integer i) {
return i;
}
@Override
public void test11() {
}
}
MyDao2.java
public interface MyDao2 {
Integer count21(Integer i);
Integer count22(Integer i);
}
public class MyDao2Impl implements MyDao2 {
@Override
public Integer count21(Integer i) {
return i;
}
@Override
public Integer count22(Integer i) {
return i;
}
}
MyServiceImpl.java
public interface MyService {
Integer count();
}
public class MyServiceImpl implements MyService {
private MyDao1 myDao1;
private MyDao2 myDao2;
private static int V = 10;
public MyServiceImpl(MyDao1 myDao1, MyDao2 myDao2) {
this.myDao1 = myDao1;
this.myDao2 = myDao2;
}
@Override
public Integer count() {
Integer result1 = myDao1.count11(10);
Integer result2 = myDao2.count21(10);
Integer result3 = value(10);
increaseV(10);
return result1 + result2 + result3 + V;
}
public static Integer value(Integer i) {
return i;
}
public static void increaseV(Integer i) {
V = V + i;
}
}
3.测试类
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.*;
import java.lang.reflect.Field;
public class MyServiceImplTest {
// 用于创建一个主要的对象(通常是要测试的对象),并且自动注入所有使用 @Mock 或 @Spy 注解的依赖项
// 只能能标注在类上,标志在接口上会报错
@InjectMocks
private MyServiceImpl myService;
// 可标注在接口上和类上
// 如果是类,值相当于会实例化,如果是接口,会生成一个实现类
// 模拟对象的所有方法都不会调用其实际实现,而是返回默认值或根据定义的行为返回值
// 相当于 MyDao1Impl myDao1 = Mockito.mock(MyDao1Impl.class)
@Mock
// private MyDao1 myDao1;
private MyDao1Impl myDao1;
// 可标注在接口上和类上
// 间谍对象是一个真实的对象,但你可以选择性地模拟其中的一些方法
// 相当于 MyDao2Impl myDao2 = Mockito.spy(MyDao2Impl.class);
@Spy
// private MyDao2 myDao2;
private MyDao2Impl myDao2;
private AutoCloseable openMocks;
private MockedStatic mockedStatic;
@Before
public void before() {
// 初始化模拟对象
// 在 Mockito 2.x 中,通常使用 @RunWith(MockitoJUnitRunner.class) 或者 @ExtendWith(MockitoExtension.class) 来自动初始化模拟对象,
// 在 Mockito 3 中,推荐的做法是使用 MockitoAnnotations.openMocks(this);。
// 如果使用的是 JUnit 5,可以考虑使用 @ExtendWith(MockitoExtension.class),这会自动调用 openMocks(this),因此你无需在 @BeforeEach 方法中显式调用它。但是,在某些情况下,你可能仍然需要显式调用 openMocks(this),比如在静态上下文中或当需要更细粒度的控制时。
openMocks = MockitoAnnotations.openMocks(this);
// 模拟有返回值的方法
Mockito.when(myDao1.count11(Mockito.any())).thenReturn(100);
Mockito.when(myDao2.count21(Mockito.any())).thenReturn(100);
// 模拟无返回值的方法
Mockito.doNothing().when(myDao1).test11();
// Mockito 3.4.0 版本之后增加了对 Static 方法的支持
// 模拟有返回值的静态方法
// 这个方法会 mock 指定类的所有 static 方法,会返回默认值或根据定义的行为返回值,像所有静态方法上,加上了 @mock
mockedStatic = Mockito.mockStatic(MyServiceImpl.class);
// 模拟无返回值的静态方法
// Mockito.when(MyServiceImpl.value(Mockito.any())).thenReturn(100);
mockedStatic.when(() -> MyServiceImpl.value(Mockito.any())).thenReturn(100);
// 模拟静态方法无返回值
mockedStatic.when(() -> MyServiceImpl.increaseV(Mockito.any())).thenAnswer(invocation -> {
// 修改私有静态变量 V 的值
Field field = MyServiceImpl.class.getDeclaredField("V");
field.setAccessible(true);
field.setInt(null, 100);
return null;
});
}
@Test
public void testCount1() {
Integer i11 = myDao1.count11(1); // 使用过 Mockito.when,返回 100
Integer i12 = myDao1.count12(1); // @Mock myDao1,会被 mock,返回默认值 0
Integer i21 = myDao2.count21(1); // 使用过 Mockito.when,返回 100
Integer i22 = myDao2.count22(1); // @Spy myDao2,不会被 mock
Assert.assertEquals(Integer.valueOf(100), i11);
Assert.assertEquals(Integer.valueOf(0), i12);
Assert.assertEquals(Integer.valueOf(100), i21);
Assert.assertEquals(Integer.valueOf(1), i22);
Integer count = myService.count();
Assert.assertEquals(Integer.valueOf(400), count);
}
@Test
public void testCount2() {
Integer count = myService.count();
Integer expected = 400;
Assert.assertEquals(expected, count);
}
@After
public void after() throws Exception {
if (openMocks != null) {
openMocks.close();
}
if (mockedStatic != null) {
mockedStatic.close();
}
}
}
4.Mockito.when、Mockito.doReturn、Mockito.doAnswer、Mockito.doNothing、Mockito.mockStatic、Mockito.verify
4.1
参数:
Mockito.when(methodCall).thenReturn(value)
Mockito.when(methodCall).then(answer);
Mockito.when(methodCall).thenAnswer(answer);
Mockito.doReturn(toBeReturned).when(mock);
Mockito.doAnswer(answer).when(mock);
在使用了Spies对象(@Spy注解)的情况下他们调用的结果是不相同的
when(...) thenReturn(...) 会调用真实的方法;
doReturn(...) when(...) 不会调用真实方法。
// 模拟有返回值的方法
Mockito.when(myDao1.count11(Mockito.any())).thenReturn(100);
Mockito.when(myDao1.count11(Mockito.any())).then(invocation -> {
Object[] arguments = invocation.getArguments();
Method method = invocation.getMethod();
return 100;
});
Mockito.when(myDao1.count11(Mockito.any())).thenAnswer(invocation -> {
System.out.println("- - -");
Object[] arguments = invocation.getArguments();
Method method = invocation.getMethod();
return 100;
});
Mockito.doReturn(100).when(myDao1).count11(Mockito.any());
Mockito.doAnswer(invocation -> {
Object[] arguments = invocation.getArguments();
Method method = invocation.getMethod();
return 100;
}).when(myDao1).count11(Mockito.any());
4.2
参数:
Mockito.doNothing().when(mock);
Mockito.doNothing().when(myDao1).test11();
4.3
参数:
Mockito.mockStatic(classToMock).thenReturn(verification);
Mockito.mockStatic(classToMock).when(verification);
Mockito.mockStatic(classToMock).thenAnswer(verification);
MockedStatic mockedStatic = Mockito.mockStatic(MyServiceImpl.class);
mockedStatic.when(() -> MyServiceImpl.value(Mockito.any())).thenReturn(100);
mockedStatic.when(() -> MyServiceImpl.value(Mockito.any())).then(invocation -> {
Object[] arguments = invocation.getArguments();
Method method = invocation.getMethod();
return 100;
});
mockedStatic.when(() -> MyServiceImpl.value(Mockito.any())).thenAnswer(invocation -> {
Object[] arguments = invocation.getArguments();
Method method = invocation.getMethod();
return 100;
});
4.4
参数:
Mockito.verify(mock);
Mockito.verify(mock, mode);
// 验证方法调用
List mockList = Mockito.mock(List.class);
mockList.add("aa");
mockList.add("bb");
mockList.add("bb");
Mockito.verify(mockList).add("aa");
Mockito.verify(mockList, Mockito.times(2)).add("bb");