我一直在尝试对此方案进行测试,但是找不到测试的好方法。因此,该测试中的此方法创建了某些自定义类型的新对象,该对象以后调用一种方法。初始化。我正在测试我的测试失败的课程和课程之间没有关系。没有任何模拟框架,就可以进行测试。我也无法更改源代码。如果是不良的代码,我仍然可以对其进行测试。
class DocuSigRESTProvider{
public IDocumentSet sendDocuments() {
/// code...
ITransformer transformer = new SendDocumentsRESTTransformer();
ITransformerResult result = transformer.transformRequest(args);
}
}
当代码进入transformrequest((时,它由于某些字段而炸毁。它总是创建一个新的,因此即使在我的测试类中我创建了一个senddocumentRestTransformer的实例,它也不会在运行时找到要初始化的特定字段。
junit
private SendDocumentsRESTTransformer sendDocumentRESTTransfomer;
private ITransformerResult iTransformerResult;
sendDocumentRESTTransfomer = mock( SendDocumentsRESTTransformer.class );
iTransformerResult = mock( ITransformerResult.class );
@Test
public void testSendDocuments() throws Exception {
DocusignRESTProvider docusignRestProvider = new DocusignRESTProvider();
docusignRestProvider.setLoggingHandler( iloggingHandler );
docusignRestProvider.setDocumentManager( iDocumentManager );
docusignRestProvider.setConfiguration( iProviderConfiguration );
docusignRestProvider.setManager( idocTranManager );
docusignRestProvider.setEmailProcessor( emailProcessor );
List<IDocumentDto> iDocumentDtoList = new ArrayList<>();
iDocumentDtoList.add( iDocumentDto );
List<IDocument> iDocumentList = new ArrayList<>();
iDocumentList.add( iDocument );
when( restProvider.loadDocuments( iClientUserDto, iDocumentSet ) ).thenReturn( iDocumentDtoList );
when( iDocumentSet.getDocuments() ).thenReturn( iDocumentList );
when( restProvider.validateDocs( anyListOf( IDocument.class ), anyListOf( IDocumentDto.class ) ) ).thenReturn( iDocumentDtoList );
PowerMockito.whenNew( SendDocumentsRESTTransformer.class ).withAnyArguments().thenReturn( sendDocumentRESTTransfomer );
when( sendDocumentRESTTransfomer.transformRequest( any( ITransformerArgs.class ) ) ).thenReturn( iTransformerResult );
iDocumentSet = docusignRestProvider.sendDocuments( iClientUserDto, iDocumentSet );
assertNotNull( iDocumentSet );
}
此代码可以测试吗?
您可以创建一个setter
方法来注入外部依赖关系。这样的东西。
class DocuSigRESTProvider{
private ITransformer transformer = new SendDocumentsRESTTransformer();
public IDocumentSet sendDocuments() {
/// code...
ITransformerResult result = transformer.transformRequest(args);
}
//package level method
void setTransformer(ITransformer transformer) {
this.transformer = transformer
}
}
然后您可以从测试类中注入stub
对象。
@Test
public void myTest() {
DocuSigRESTProvider docusignRestProvider = new DocuSigRESTProvider();
docusignRestProvider.setTransformer(new SendDocumentsRESTTransformerStub());
//...rest of test code.
}
private class SendDocumentsRESTTransformerStub extends SendDocumentsRESTTransformer {
//... Override methods.
}
必须以某种方式编写一般代码,才能进行单位测试。您不能只采用任何(任意的(代码并以干净的方式进行测试。
因此,您应该遵守一些惯例/遵循一些实践。提供的代码片段并没有真正遵循这些实践,因此您被迫使用PowerMock,只有在绝对没有其他选择的情况下,才能使用PowerMock(如果有的话(。我个人尝试避免尽可能多地使用Power Mock。
第一个经验法则是使用依赖项注入,而不是使用new
关键字在方法中创建对象。
所以让我们稍微更改您的代码:
class DocuSigRESTProvider{
private ITransformer transformer;
public DocuSigRESTProvider(ITransformer transformer) {
this.transformer = transformer;
}
public IDocumentSet sendDocuments() {
/// code...
ITransformerResult result = transformer.transformRequest(args);
}
}
那么我们实际上获得了什么?很多事情:DocuSigRESTProvider
类并不涉及创建ITRansFormer实现(的确为什么要打扰,它应该宁愿获得接口并对其进行使用(。界面实现是从外部注入(请阅读有关构造仪注入,设置器注入等等,我不会潜入依赖性注入,因为它本身就是一个广泛的话题(。
因此,应该检查"代码"部分中写的内容(毕竟您检查了sendDocuments
方法(,直到您到达最后一行,这是变压器调用。
现在您确实想模拟/固执变压器,但是这次(这是一个重大的改进!(您应该模拟界面而不是真实的实现。使用这种方法,您可以使用EasyMock/Mockito-它们都可以为接口创建模拟,甚至可以根据需要制作自己的"假"实现。