如何解决无法识别Mockito.spy对象
我正在尝试测试以下方法:
@Override
public Target apply(Source source) throws MappingException {
try {
Target target = targetModelObjectFactory.create(Target.class);
mapNameToFirstName(source,target);
mapMailToEMail(source,target);
mapSourceSubEntityToTargetSubEntity(source,target);
mapPrimitiveSourceColToPrimitiveTargetCol(source,target);
mapSubEntitiesSourceColToSubEntitiesTargetCol(source,target);
mapSourceSubEntityFieldToSubEntityFetchedField(source,target);
produceProducedFieldValue(target);
setConstantFieldConstantValue(target);
return target;
} catch (Exception e) {
throw new MappingException(source,e);
}
}
这是我测试的一部分:
public void TestApply() throws MappingException,MappingOperatorCreationException,TargetModelObjectCreationException {
Source mockedSource = Mockito.mock(Source.class);
Target mockedTarget = Mockito.mock(Target.class);
TargetModelObjectFactory targetModelObjectFactory = Mockito.spy(TargetModelObjectFactory.class);
Mockito.when(targetModelObjectFactory.create(Target.class)).thenReturn(mockedTarget);
sourceToTargetMapper.apply(mockedSource);
}
我遇到的问题是这部分:
Target target = targetModelObjectFactory.create(Target.class);
在我正在测试的apply函数中对targetModelObjectFactory
值进行辩论时,其值为“'this'is not available”,并且我继续获取NullPointerException
targetModelObjectFactory
是接口的节点
我一直在尝试这样做:
TargetModelObjectFactory targetModelObjectFactory1 = Mockito.mock(TargetModelObjectFactory.class,Mockito.RETURNS_DEEP_STUBS);
但仍然没有运气
任何帮助将不胜感激
解决方法
问题的主要根源是测试中没有注入模拟的targetModelObjectFactory
对象。
当您在类TargetModelObjectFactory
上进行模拟/间谍时,您获得的对象绝不会传递给已测试的类,
因此它的引用为null,因此在实际为空的引用上尝试调用方法NullPointerException
时抛出create
。
根据您所测试的课程的其余部分(我只能猜测),您可以选择两种方法。第一个是构造函数注入 (通常,您可以阅读更多here):
class SourceToTargetMapper {
private TargetModelObjectFactory targetModelObjectFactory;
SourceToTargetMapper(TargetModelObjectFactory targetModelObjectFactory) {
this.targetModelObjectFactory = targetModelObjectFactory;
}
}
第二个是字段注入,这取决于@Inject
,@Autowired
等注释,具体取决于所使用的工具:
class SourceToTargetMapper {
@Autowired
private TargetModelObjectFactory targetModelObjectFactory;
}
两种情况都可以使用Mockito轻松处理:
@Test
void constructorInjectionTest() {
TargetModelObjectFactory factory = mock(TargetModelObjectFactory.class);
SourceToTargetMapper mapper = new SourceToTargetMapper(factory);
Source source = mock(Source.class);
Target target = mock(Target.class);
when(factory.create(Target.class))
.thenReturn(target);
Target result = mapper.apply(source);
assertSame(target,result);
}
@Mock
TargetModelObjectFactory factory;
@InjectMocks
private SourceToTargetMapper mapper;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
void fieldInjectionTest() {
Source source = mock(Source.class);
Target target = mock(Target.class);
when(factory.create(Target.class))
.thenReturn(target);
Target result = mapper.apply(source);
assertSame(target,result);
}
值得注意的另一件事是Mockito库中mock
和spy
方法之间的区别。
使用mock
时,该类的整个行为由Mockito处理,这就是为什么我们使用一个Class
参数对其进行调用的原因:
FirstClass firstObject = mock(FirstClass.class);
SecondClass secondObject = mock(SecondClass.class);
没有创建FirstClass
和SecondClass
的实际实例。
使用spy
时,我们明确告诉Mockito,哪些方法应更改其行为,哪些方法应实际调用
按照课程中的定义。我们可以使用Class
参数或实际对象(经常使用后者)来创建间谍。
对于间谍而言,实际行为通常根本不会改变,因为可以使用间谍来检查该方法是否真正被调用:
MyClass object = spy(new MyClass());
doStuff(object);
verify(object,times(1))
.myMethod();
在您的情况下,由于您更改了TargetModelObjectFactory
类的行为,因此mock
可能是一个更好的选择。
我创建了一个repository on GitHub,您可以在其中找到所有代码-所有测试都通过。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。