问题描述
我有以下测试,我需要验证是否正在调用Person类的所有getter。到目前为止,我已经使用了mockito的verify()来确保调用每个getter。有没有办法通过反思来做到这一点?可能会在Person类中添加一个新的getter,但测试将错过。
I have the following test where I need to verify that all getters of the Person class are being called. So far I have used mockito's verify() to make sure that each getter is called. Is there a way to do that by reflection? It can be the case that a new getter is added to the Person class but the test will miss that.
public class GetterTest {
class Person{
private String firstname;
private String lastname;
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
}
@Test
public void testAllGettersCalled() throws IntrospectionException{
Person personMock = mock(Person.class);
personMock.getFirstname();
personMock.getLastname();
for(PropertyDescriptor property : Introspector.getBeanInfo(Person.class).getPropertyDescriptors()) {
verify(personMock, atLeast(1)).getFirstname();
//**How to verify against any getter method and not just getFirstName()???**
}
}
}
推荐答案
一般情况下,不要模拟测试中的类。如果你的测试是针对一个人的,你不应该在其中看到 Mockito.mock(Person.class)
,因为这是一个非常清楚的迹象表明你正在测试模拟框架而不是被测系统。
Generally, don't mock the class under test. If your test is for a Person, you shouldn't ever see Mockito.mock(Person.class)
in it, as that's a pretty clear sign that you're testing the mocking framework instead of the system-under-test.
相反,你可能想创建一个 spy(new Person())
,它将使用真实的构造函数创建一个真实的Person实现,然后将其数据复制到Mockito生成的代理。您可以使用 MockingDetails.getInvocations()
反思检查是否已调用每个getter。
Instead, you may want to create a spy(new Person())
, which will create a real Person implementation using a real constructor and then copy its data to a Mockito-generated proxy. You can use MockingDetails.getInvocations()
to reflectively check that every getter was called.
// This code is untested, but should get the point across. Edits welcome.
// 2016-01-20: Integrated feedback from Georgios Stathis. Thanks Georgios!
@Test
public void callAllGetters() throws Exception {
Person personSpy = spy(new Person());
personSpy.getFirstname();
personSpy.getLastname();
assertAllGettersCalled(personSpy, Person.class);
}
private static void assertAllGettersCalled(Object spy, Class<?> clazz) {
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
Set<Method> setOfDescriptors = beanInfo.getPropertyDescriptors()
.stream()
.map(PropertyDescriptor::getReadMethod)
.filter(p -> !p.getName().contains("getClass"))
.collect(Collectors.toSet());
MockingDetails details = Mockito.mockingDetails(spy);
Set<Method> setOfTestedMethods = details.getInvocations()
.stream()
.map(InvocationOnMock::getMethod)
.collect(Collectors.toSet());
setOfDescriptors.removeAll(setOfTestedMethods);
// The only remaining descriptors are untested.
assertThat(setOfDescriptors).isEmpty();
}
可能有办法调用验证在Mockito生成的间谍上,code>和
调用
,但这看起来非常脆弱,并且非常依赖于Mockito内部。
There might be a way to call verify
and invoke
on the Mockito-generated spy, but that seems very fragile, and very dependent on Mockito internals.
顺便说一下,测试bean风格的getter似乎是时间/精力的奇怪用法。通常侧重于测试可能会改变或破坏的实现。
As an aside, testing bean-style getters seems like an odd use of time/effort. In general focus on testing implementations that are likely to change or break.
这篇关于验证是否已调用所有getter方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!