【问题标题】:Verify a static method was called by another static method in PowerMock验证一个静态方法是否被 PowerMock 中的另一个静态方法调用
【发布时间】:2014-01-29 21:43:22
【问题描述】:

我有一个带有两个静态方法的 Tool 类,doSomething(Object) 和 callDoSomething()。名称很直观,因为 callDoSomething 将其调用委托给 doSomething(Object);

public class Tool
{
  public static void doSomething( Object o )
  {
  }
  public static void callDoSomething()
  {
    doSomething( new Object());
  }
}

我有一个用于 Tool 的测试类,我想验证是否调用了 doSomething(Object)(我将来也想做参数匹配)

@RunWith( PowerMockRunner.class )
@PrepareForTest( { Tool.class } )
public class ToolTest
{
  @Test
  public void toolTest()
  {
    PowerMockito.mockStatic( Tool.class );
    Tool.callDoSomething();// error!!
    //Tool.doSomething();// this works! it gets verified!
    PowerMockito.verifyStatic();
    Tool.doSomething( Mockito.argThat( new MyArgMatcher() ) );
  }

  class MyArgMatcher extends ArgumentMatcher<Object>
  {
    @Override
    public boolean matches( Object argument )
    {
      return true;
    }
  }
}

如果直接调用,Verify 会选择 doSomething(Object)。我已经在上面注释掉了这段代码。验证在使用 callDoSomething 时不会选择 doSomething(Object)(这是上面显示的代码)。这是我运行上面代码时的错误日志:

Wanted but not invoked tool.doSomething(null);

However, there were other interactions with this mock.
    at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
    at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:192)
    at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:105)
    at org.powermock.core.MockGateway.methodCall(MockGateway.java:60)
    at Tool.doSomething(Tool.java)
    at ToolTest.toolTest(ToolTest.java:22) 
... [truncated]

我想避免对 Tool 类进行任何更改。我的问题是,如何验证 doSomething(Object) 是从 callDoSomething() 调用的,以及对 doSomething 的参数执行一些参数匹配

【问题讨论】:

    标签: android mockito powermock android-testing


    【解决方案1】:

    听起来您想使用静态间谍(部分模拟)。谈到模拟静态的section of the PowerMock documentation 在第二个项目符号中有一个很容易漏掉的注释:

    (使用 PowerMockito.spy(class) 模拟特定方法)

    请注意,在您的示例中,您实际上并没有模拟行为,只是验证调用了该方法。有一个微妙但重要的区别。如果您不想调用 doSomething(Object),则需要执行以下操作:

    @Test
    public void toolTest() {
        PowerMockito.spy(Tool.class); //This will call real methods by default.
    
        //This will suppress the method call.
        PowerMockito.doNothing().when(Tool.class);
        Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
    
        Tool.callDoSomething();
    
        //The rest isn't needed since you're already mocking the behavior
        //but you can still leave it in if you'd like.
        PowerMockito.verifyStatic();
        Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
    }
    

    如果您仍然希望该方法触发,只需删除 doNothing() 的两行。 (我在我的 Tool.java 版本中添加了一个简单的System.out.println("do something " + o); 作为doNothing() 的附加验证。)

    【讨论】:

      【解决方案2】:

      您可以通过以下方式进行验证:

      public class Tool{
      
        public static boolean isFromCallDoSomethingMethod= false;
      
      
      
      
      
      
      
        public static void doSomething(Object o){
      
        }
      
      
      
      
      
      
      
      
        public static void callDoSomething() {
      
            doSomething(new Object());
      
            isFromCallDoSomethingMethod= true;
      
        }
      
      
      
      
      
      
      
      
      }
      

      您可以进行验证:

          if(Tool.isFromCallDoSomethingMethod){
      
              //you called doSomething() from callDoSomething();
      
          }
      

      记住

      如果您从不是来自callDoSomething() 的其他方式调用doSomething(),请不要忘记进行验证,您可以通过使用Tool.isFromCallDoSomethingMethod = false 来完成此操作

      这是你想要的吗?

      【讨论】:

      • 感谢您的建议!我想避免更改 Tool 类,我应该在前面提到过。
      猜你喜欢
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 1970-01-01
      • 2016-06-26
      相关资源
      最近更新 更多