# mockito
# 常用静态方法
thenReturn
thenAnswer
thenThrow
doReturn
doThrow
doAnswer
MockedConstruction<T>
MockedStatic<T>
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# mock静态方法

# @Mock与@Spy
spy可打桩方法内部的公共方法

# mock方法内部new出来的对象
# mock有参构造函数
但是在这个用例中,在处理一个对象时,需要每次生成对象,都让这个对象的某个方法的表现是被替代的。 这个时候很多人会想到:
Person person = Mockito.spy(Person.class);
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
Mockito.when(person.say()).thenReturn("mock for say.");
1
2
3
2
3
然后就可以只对每个Person对象的say方法进行mock,而其他方法执行实际代码逻辑。
接下来,尝试仅使用Mockito的方式进行这个实践
首先观察Mockito的方法,有两个方法名与构造函数有关:mockConstruction、mockConstructionWithAnswer
接下来尝试mockConstruction,发现如何mock,都无法实现上面的效果,没有被Mockito.when的方法默认是doNothing策略,导致无法达成测试用例的目的
Mockito.mockConstruction(Person.class, (person, context) -> {
// 各种mock尝试
});
1
2
3
2
3
那么只能用mockConstructionWithAnswer继续进行尝试,
方法签名:
public static <T> MockedConstruction<T> mockConstructionWithAnswer(
Class<T> classToMock, Answer defaultAnswer, Answer... additionalAnswers) {
return mockConstruction(
classToMock,
context -> {
if (context.getCount() == 1 || additionalAnswers.length == 0) {
return withSettings().defaultAnswer(defaultAnswer);
} else if (context.getCount() >= additionalAnswers.length) {
return withSettings()
.defaultAnswer(additionalAnswers[additionalAnswers.length - 1]);
} else {
return withSettings()
.defaultAnswer(additionalAnswers[context.getCount() - 2]);
}
},
(mock, context) -> {});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
观察方法签名,显然需要我们实现一个answer进行传入,通过观察,invocation对象拥有方法的对象,以及方法的对应入参,那么可以使用类反射的机制直接突破困境,如下面的代码
Person person = Mockito.spy(Person.class);
Mockito.when(person.say()).thenReturn("mock for say.");
Mockito.mockConstructionWithAnswer(Person.class, new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return invocation.getMethod().invoke(person, invocation.getArguments());
}
});
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8