验证静态方法被称为在另一PowerMock静态方法静态、方法、被称为、PowerMock

2023-09-07 02:24:35 作者:希洛梦

我有两个静态方法,DoSomething的(对象)和callDoSomething()工具类。名称是直观的在callDoSomething代表其调用DoSomething的(对象);

I have a Tool class with two static methods, doSomething(Object) and callDoSomething(). The names are intuitive in that callDoSomething delegates its call to doSomething(Object);

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

我有工具测试类,我想,以验证是否DoSomething的(对象)被称为(我想要做的参数在将来匹配太)

I have a Test class for Tool and I'd like to verify if doSomething(Object) was called (I want to do Argument Matching too in the future)

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

验证回升DoSomething的(对象),如果它直接调用。我上面这个评论code OUT。验证使用callDoSomething时不拿起DoSomething的(对象),(这是上面显示的code)。这是我的错误日志运行上述code时:

Verify picks up doSomething(Object) if it's called directly. I've commented this code out above. Verify does NOT pick up doSomething(Object) when using callDoSomething, (this is the code shown above). This is my error log when running the code above:

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]

我想避免的工具类中的任何变化。我的问题是,我怎么能确认DoSomething的(对象)从callDoSomething(叫),以及对DoSomething的的参数进行一些参数的匹配

I'd like to avoid making any changes to the Tool class. My question is, how can I verify doSomething(Object) was called from callDoSomething(), as well as perform some argument matching on doSomething's param

推荐答案

这听起来像你想使用静态谍照(部分模拟)。在PowerMock文档的部分大约嘲讽静态会谈有在第二个项目符号一张纸条,上面可以很容易错过:

It sounds like you want to use a static spy (partial mock). The section of the PowerMock documentation that talks about mocking static has a note in the second bullet that could be easily missed:

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

(use PowerMockito.spy(class) to mock a specific method)

请注意,在你的榜样,你实际上并没有嘲讽的行为,只是验证方法被调用。有一个微妙但重要的区别。如果你不想让 DoSomething的(对象)来叫你需要做这样的事情:

Note, in your example you're not actually mocking the behavior, just verifying the method is called. There's a subtle but important difference. If you don't want doSomething(Object) to be called you'd need to do something like this:

@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()。 (我添加了一个简单的的System.out.println(有所作为+ O); 来我的版本Tool.java为的附加验证doNothing()

If you still want the method to fire though, just remove the two lines for doNothing(). (I added a simple System.out.println("do something " + o); to my version of Tool.java as an additional verification of doNothing().)