使用JMockit或Mockito模拟带有void返回类型的方法调用

时间:2013-07-16 16:48:06

标签: unit-testing junit mocking mockito jmockit

我有一种非常不同的方法调用,我需要使用JMockit测试框架进行测试。首先让我们看一下代码。

public class MyClass{

   MyPort port;       

   public registerMethod(){
       Holder<String> status=null;
       Holder<String> message=null;

       //below method call is a call to a webservice in the real implementation using apache cxf framework. This method has a void return type. Read below for better explanation.
       port.registerService("name", "country", "email", status, message);

       // do some stuff with status and message here.....

       HashMap response = new HashMap();
       response.put(status);
       response.put(message);

       return response;
   }  

}

现在让我解释一下。这个类基本上有一个端口实例变量,用于连接web服务。 Web服务实现使用自动生成的apache cxf框架类来建立与Web服务的连接并获取响应。我的工作是实现对这个webservice调用的模拟,为很多类似的调用编写测试用例。

这里的问题是 - 如果你注意到通过发送名称,国家和电子邮件作为参数,方法port.registerService实际上是对webservice的调用。现在我们还将状态和消息变量作为参数本身传递给此方法。所以这个方法不是为状态和消息返回一些值,而是在这两个传递的参数中FILLS IN值,这与“RETURN”方法非常不同。

现在的问题是当我试图使用jmockit模拟这个调用时,我总是可以模拟这个调用,但是可以预料到什么?由于根本没有返回,它结果是一个无效调用,它填充传递给它的参数中的值。所以我总是得到状态,如果我模拟这个调用,则消息为null,因为我无法在jmockit实现中声明任何返回期望。

如果有人对上述问题有任何解决方案/建议,请做出回应并尽力帮助我。感谢。

1 个答案:

答案 0 :(得分:1)

我不确定Holder界面是什么样的,所以我做了一些假设。但是,这是使用Mockito模拟具有void返回类型的方法的方法:

@SuppressWarnings("unchecked")
@Test
public final void test() {
    // given
    final String expectedStatus = "status";
    final String expectedMessage = "message";
    final MyPort mockPort = mock(MyPort.class);
    final Answer<Void> registerAnswer = new Answer<Void>() { // actual parameter type doesn't matter because it's a void method
        public Void answer(final InvocationOnMock invocation) throws Throwable {
            // Here I'm stubbing out the behaviour of registerService
            final Object[] arguments = invocation.getArguments();
            // I don't actually care about these, but if you wanted the other parameters, this is how you would get them
            // if you wanted to, you could perform assertions on them
            final String name = (String) arguments[0];
            final String country = (String) arguments[1];
            final String email = (String) arguments[2];

            final Holder<String> statusHolder = (Holder<String>) arguments[3];
            final Holder<String> messageHolder = (Holder<String>) arguments[4];
            statusHolder.put(expectedStatus);
            messageHolder.put(expectedMessage);
            // even though it's a void method, we need to return something
            return null;
        }
    };
    doAnswer(registerAnswer).when(mockPort).registerService(anyString(),
            anyString(), anyString(), any(Holder.class), any(Holder.class));

    final MyClass object = new MyClass();
    object.port = mockPort;

    // when
    final Map<String, String> result = object.registerMethod();

    // then
    assertEquals(expectedStatus, result.get("status"));
    assertEquals(expectedMessage, result.get("message"));
}

供参考,这些是我的进口商品:

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;

import java.util.HashMap;
import java.util.Map;

import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;