Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 使用JMockit或Mockito模拟具有void返回类型的方法调用_Unit Testing_Junit_Mocking_Mockito_Jmockit - Fatal编程技术网

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

Unit testing 使用JMockit或Mockito模拟具有void返回类型的方法调用,unit-testing,junit,mocking,mockito,jmockit,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 webs

我有一种非常不同的方法调用,我需要使用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;
   }  

}
公共类MyClass{
我的港口;
公共注册方法(){
持有人状态=空;
持有者消息=null;
//下面的方法调用是在使用apache cxf框架的实际实现中对webservice的调用。此方法的返回类型为void。请阅读下面的内容以获得更好的解释。
端口注册服务(“名称”、“国家”、“电子邮件”、状态、消息);
//在这里做一些关于状态和消息的事情。。。。。
HashMap响应=新建HashMap();
答复.付诸表决(状态);
响应.放置(消息);
返回响应;
}  
}
现在让我解释一下。这个类基本上有一个端口实例变量,用于连接到Web服务。webservice实现使用自动生成的apachecxf框架类连接到webservice并获取响应。我的工作是实现这个webservice调用的模拟,以便为实际应用程序中的许多类似调用编写测试用例

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

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


如果有人对上述问题有任何解决方案/建议,请务必回复并尝试帮助我。谢谢。

我不确定
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"));
}

我不确定
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"));
}

您可以使用
result=newdelegate(){void Delegate(…){…}模拟模拟的
port.registerService(…)
方法的行为记录期望值。这将允许测试指定所需的副作用。但是在没有看到测试中的完整方法的情况下,我无法确定这是否是您所需要的…这里的问题是,实际的方法调用只是在status和message变量中设置变量中的值,而没有返回任何内容。是的,但是那又怎么样?我不明白。如果该方法正在被模拟,那么它的实现做什么并不重要。在任何情况下,您的测试都可以完全控制任何模拟方法的行为。感谢您对rogerio的评论。我的观点是,请看上面的代码,在我调用port.registerService(…)的那一行中,我也传递参数、状态和消息。现在,在这个调用之后,我在代码中使用这些变量来设置其他一些使用这些值的东西。但是,在模拟的情况下,这将始终保持null,因为这些值是在void方法中设置的,并且不会返回,因此我无法使用jmockit中的期望值来设置这些值。是的,如果局部变量从未分配任何其他值,则它们将保持
null
。我还是看不出有什么问题。正如我之前所说,从测试中,您可以完全控制模拟方法的行为,包括
registerService
。模拟无法进入方法内部的局部变量并对其进行设置…您可以使用
result=new Delegate(){void Delegate(…){…}模拟模拟的
port.registerService(…)
方法的行为记录期望值。这将允许测试指定所需的副作用。但是在没有看到测试中的完整方法的情况下,我无法确定这是否是您所需要的…这里的问题是,实际的方法调用只是在status和message变量中设置变量中的值,而没有返回任何内容。是的,但是那又怎么样?我不明白。如果该方法正在被模拟,那么它的实现做什么并不重要。在任何情况下,您的测试都可以完全控制任何模拟方法的行为。感谢您对rogerio的评论。我的观点是,请看上面的代码,在我调用port.registerService(…)的那一行中,我也传递参数、状态和消息。现在,在这个调用之后,我在代码中使用这些变量来设置其他一些使用这些值的东西。但是,在模拟的情况下,这将始终保持null,因为这些值是在void方法中设置的,并且不会返回,因此我无法使用jmockit中的期望值来设置这些值。是的,如果局部变量从未分配任何其他值,则它们将保持
null
。我还是看不出有什么问题。正如我之前所说,从测试中,您可以完全控制模拟方法的行为,包括
registerService
。模拟无法进入方法内部的局部变量并设置它。。。