如何在没有Mockingn框架的情况下测试在另一个类中调用另一个方法的方法

时间:2017-04-19 19:20:51

标签: java junit mockito powermock

我一直试图对此方案进行测试,但我无法找到测试它的好方法。所以这个测试中的方法会创建一个特定自定义类型的新Object,然后调用一个方法。现在调试时我的代码到达这一点时它会检测到正在创建的新对象但是当它进入方法时会因为某些字段没有而爆炸初始化。我正在测试的类和我的测试失败的类之间没有任何关系。没有任何Mocking框架就有办法测试这个。我也无法更改源代码。如果它是一个糟糕的代码,我仍然可以测试它。

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 );
}

此代码是否可测试?

2 个答案:

答案 0 :(得分:1)

通常,代码必须以某种方式编写才能进行单元测试。你不能只采取任意(任意)的代码,并以干净的方式对其进行单元测试。

所以,你应该遵守一些惯例/遵循一些做法。提供的代码段并不真正遵循这些做法,因此您不得不使用PowerMock,只有在绝对没有其他选择的情况下才应该使用PowerMock(如果有的话)。我个人尽量避免使用电源模拟。

第一个经验法则是使用依赖注入,而不是使用new关键字在方法中创建对象。

所以,让我们稍微更改您的代码:

class DocuSigRESTProvider{
  private ITransformer transformer;

  public DocuSigRESTProvider(ITransformer transformer) {
     this.transformer = transformer;
  }

  public IDocumentSet sendDocuments() {
     /// code...
     ITransformerResult result = transformer.transformRequest(args);
  }
}

那么我们实际获得了什么?很多:DocuSigRESTProvider类没有处理创建ITransformer的实现(实际上为什么它应该打扰,它应该更好地获得一个接口并对其起作用)。界面实现从外部注入(阅读构造函数注入,setter注入等等,我不会深入研究依赖注入,因为它本身就是一个广泛的主题)。 / p>

所以测试应该检查&#34;代码&#34;在你到达变压器调用的最后一行之前,部分(毕竟你检查一个sendDocuments方法)不应再创建。

现在你确实想要模拟/存根变换器,但这次(这是一个重大改进!)你应该模拟接口而不是真正的实现。使用这种方法,您可以使用EasyMock / Mockito - 它们都可以创建界面模拟,甚至可以制作自己的假冒&#34;假的&#34;如果你愿意,可以实施。

答案 1 :(得分:1)

您可以创建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.
}