为什么我不能监视枚举方法?我可以嘲笑并监视我需要的所有其他内容,但是当我试图监视枚举时,我的测试不再运行,我只是得到初始化错误。
枚举类:
public enum DomainResource implements SoapUpdate {
ENUM1(new PUpdate()),
ENUM2(new SUpdate());
private DomainResource(SoapUpdate update){
this.update = update;
}
private final SoapUpdate update;
@Override
public void apply(SoapService svc, byte[] resp ) throws Exception {
update.apply(svc, resp)
}
}
要测试的课程:
public class ProcessUpdateMessage implements Function<UpdateMessage, MessageResult> {
private DomainResource resource;
public MessageResult apply( UpdateMessage t ){
..
resource = getResourceType( t.getUrl() )
..
resource.apply( soapService, dropwizardResponse );
}
}
测试:
@RunWith(MockitoJUnitRunner.class)
public class UpdateMessageTest {
// other spies and mocks working correctly
@Spy
DomainResource resource; // error here
@InjectMocks
ProcessUpdateMessage puma = new ProcessUpdateMessage(null, null, "");
@Test
...
}
并且(我没有写过那个类)将逻辑放入java枚举中是不是很糟糕?
由于
答案 0 :(得分:3)
Mockito doesn't allow mocking final classes,其中包含枚举effectively final。但是,错误在于ProcessUpdateMessage的设计,而不是枚举类型。
枚举类型,尤其是示例中的值名称很差,这可以解释为什么您对该代码的设计有疑问。但是,无论是谁写了枚举 DID都会给你一种模拟它的方法(正如你的评论建议你发现的那样),通过使它实现接口SoapUpdate
。您需要将ProcessUpdateMessage.resource
的类型更改为SoapUpdate
,然后您至少可以模拟它(虽然查看您的代码我想知道在您的测试中,未显示,注入的模拟不会被getResourceType
)的调用结果覆盖。
在回答关于最佳实践的最后一个问题时,在枚举值中添加逻辑完全符合DRY的最佳实践。枚举类型表示已知和有限的一组可能性中的选择。如果它是暗示行为的选择,您可以强制接收枚举的任何方法来实现容易出错且冗余的switch语句,指定枚举的所有可能值的行为,或者您可以让它调用方法关于枚举值。这是DRY的一个明显案例,它也会影响代码的cyclomatic complexity。
答案 1 :(得分:0)
这是我的一个测试/我的解决方案:
@Test
public void testSoapServiceCallwithDWResponse200AndSoapProblem(){
UpdateMessage um = new UpdateMessage( "ID/123", "POST" , "/domain/resourcename/id_123" );
int status = 200;
String jsonResp = "{aLotOf:\"json\"}";
doReturn( response ) //mocked
.when( connector ).getLatestStateOfResource( anyString() );
prepareResponseMockedEntityAndStatus( status, jsonResp );
MockResource mockResource = new MockResource( "exception - resp status "+status );
doReturn( mockResource )
.when( puma ).getResourceType( anyString() );
MessageResult processingResult = puma.apply( um );
// a few verify..
Assert.assertTrue( mockResource.times() == 1 );
Assert.assertTrue( processingResult == MessageResult.NACK_REQUEUE );
}
class MockResource implements SoapUpdate{
private String name;
private int calls;
public MockResource( String name ){
this.name = name;
calls = 0;
}
public int times(){
return calls;
}
@Override
public void apply( SoapService svc, byte[] resp ) throws Exception {
calls++;
if( name.contains( "exception" ) ){
throw new Exception( name + " - Mocked `response.apply()` throws an excpt");
}
System.out.println( name + " - DB behind soap service UPDATED SUCCESSFULLY" );
}
}