如何验证静态 void 方法是否已使用 power mockito 调用

2022-01-14 00:00:00 static-methods unit-testing mockito java

我正在使用以下内容.

Powermock-mockito 1.5.12
Mockito 1.95
junit 4.11

这是我的实用程序类

public void InternalUtils {
    public static void sendEmail(String from, String[] to, String msg, String body) {
    }
}

这里是被测类的要点:

public class InternalService {
       public void processOrder(Order order) {
           if (order.isSuccessful()) {
               InternalUtils.sendEmail(...);
           }
       }
}

这是测试:

@PrepareForTest({InternalUtils.class})
@RunWith(PowerMockRunner.class)
public class InternalService {
   public void verifyEmailSend() {
        mockStatic(Internalutils.class);
        doNothing().when(InternalUtils, "sendEmail", anyString(), any(String.class), anyString(), anyString());
        Order order = mock(Order.class);
        when(order.isSuccessful()).thenReturn(true);
        InternalService is = new InternalService();

        verifyStatic(times(1));
        is.processOrder(order);
   }
}

上述测试失败.给定的验证方式是none,但是根据code,如果下单成功则必须发送email.

The above test fails. The verification mode given is none, but according to the code, if order is successful than email must be send.

推荐答案

如果你在模拟行为(使用 doNothing() 之类的东西),真的不需要调用 验证*().也就是说,这是我重写测试方法的尝试:

If you are mocking the behavior (with something like doNothing()) there should really be no need to call to verify*(). That said, here's my stab at re-writing your test method:

@PrepareForTest({InternalUtils.class})
@RunWith(PowerMockRunner.class)
public class InternalServiceTest { //Note the renaming of the test class.
   public void testProcessOrder() {
        //Variables
        InternalService is = new InternalService();
        Order order = mock(Order.class);

        //Mock Behavior
        when(order.isSuccessful()).thenReturn(true);
        mockStatic(Internalutils.class);
        doNothing().when(InternalUtils.class); //This is the preferred way
                                               //to mock static void methods.
        InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());

        //Execute
        is.processOrder(order);            

        //Verify
        verifyStatic(InternalUtils.class); //Similar to how you mock static methods
                                           //this is how you verify them.
        InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
   }
}

为了更好地突出正在发生的事情,我将其分为四个部分:

I grouped into four sections to better highlight what is going on:

我选择在这里声明任何实例变量/方法参数/模拟协作者.如果它在多个测试中使用,请考虑将其作为测试类的实例变量.

I choose to declare any instance variables / method arguments / mock collaborators here. If it is something used in multiple tests, consider making it an instance variable of the test class.

这是您定义所有模拟行为的地方.在执行被测代码之前,您在此处设置返回值和期望值.一般来说,如果您在此处设置模拟行为,则以后无需验证该行为.

This is where you define the behavior of all of your mocks. You're setting up return values and expectations here, prior to executing the code under test. Generally speaking, if you set the mock behavior here you wouldn't need to verify the behavior later.

这里没有什么花哨的;这只是启动正在测试的代码.我喜欢给它一个单独的部分来引起人们的注意.

Nothing fancy here; this just kicks off the code being tested. I like to give it its own section to call attention to it.

这是当您调用任何以 verifyassert 开头的方法时.测试结束后,您检查您希望发生的事情是否确实发生了.这是我在您的测试方法中看到的最大错误;你试图在它有机会运行之前验证方法调用.其次是您从未指定哪个要验证的静态方法.

This is when you call any method starting with verify or assert. After the test is over, you check that the things you wanted to have happen actually did happen. That is the biggest mistake I see with your test method; you attempted to verify the method call before it was ever given a chance to run. Second to that is you never specified which static method you wanted to verify.

这主要是我个人的喜好.您需要按照一定的顺序做事,但在每个分组中都有一点回旋余地.这有助于我快速区分出发生了什么.

This is mostly personal preference on my part. There is a certain order you need to do things in but within each grouping there is a little wiggle room. This helps me quickly separate out what is happening where.

我还强烈建议您浏览以下网站上的示例,因为它们非常强大,可以帮助您处理您需要的大多数案例:

I also highly recommend going through the examples at the following sites as they are very robust and can help with the majority of the cases you'll need:

  • https://github.com/powermock/powermock/wiki/Mockito (PowerMock 概述/示例)
  • http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html(Mockito 概述/示例)
  • https://github.com/powermock/powermock/wiki/Mockito (PowerMock Overview / Examples)
  • http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html (Mockito Overview / Examples)

相关文章