【问题标题】:How to verify static void method has been called with power mockito如何验证已使用 power mockito 调用了静态 void 方法
【发布时间】:2013-08-30 05:53:38
【问题描述】:

我正在使用以下内容。

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。

【问题讨论】:

    标签: java unit-testing mockito static-methods


    【解决方案1】:

    如果你在嘲笑这种行为(比如doNothing()),那么真的不需要打电话给verify*()。也就是说,这是我重写测试方法的尝试:

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

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

    1。变量

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

    2。模拟行为

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

    3。执行

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

    4。验证

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

    补充说明

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

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

    【讨论】:

    • verifyStatic(次(1)); == 验证静态();
    • 我试图验证一个返回 void 的静态方法是否被调用了一次(带有一些特定的参数)。我必须从上面的代码中删除 doNothing 语句才能让它工作。
    • 如何检查一个特定的静态方法是否被调用了两次,而另一个被调用了一次?
    • @GaneshSatpute 你最终会调用两次verifyStatic(),一次用于第一个方法(随后是第一个方法调用),另一次用于第二个方法(随后是第二个方法调用) .对于被调用两次的方法,将times(2) 传递给verifyStatic()
    【解决方案2】:

    上述答案已被广泛接受并有据可查,我找到了在此处发布答案的一些原因:-

        doNothing().when(InternalUtils.class); //This is the preferred way
                                               //to mock static void methods.
        InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
    

    在这里,我不明白为什么我们自己调用 InternalUtils.sendEmail。 我将在我的代码中解释为什么我们不需要这样做。

    mockStatic(Internalutils.class);
    

    所以,我们已经模拟了这门课。 现在,让我们看看我们需要如何验证 sendEmail(/..../) 方法。

    @PrepareForTest({InternalService.InternalUtils.class})
    @RunWith(PowerMockRunner.class)
    public class InternalServiceTest {
    
        @Mock
        private InternalService.Order order;
    
        private InternalService internalService;
    
        @Before
        public void setup() {
            MockitoAnnotations.initMocks(this);
            internalService = new InternalService();
        }
    
        @Test
        public void processOrder() throws Exception {
    
            Mockito.when(order.isSuccessful()).thenReturn(true);
            PowerMockito.mockStatic(InternalService.InternalUtils.class);
    
            internalService.processOrder(order);
    
            PowerMockito.verifyStatic(times(1));
            InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
        }
    
    }
    

    这两行是神奇之处, 第一行告诉 PowerMockito 框架它需要验证它静态模拟的类。但是它需要验证哪种方法? 第二行告诉它需要验证哪个方法。

    PowerMockito.verifyStatic(times(1));
    InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
    

    这是我班级的代码,sendEmail api 两次。

    public class InternalService {
    
        public void processOrder(Order order) {
            if (order.isSuccessful()) {
                InternalUtils.sendEmail("", new String[1], "", "");
                InternalUtils.sendEmail("", new String[1], "", "");
            }
        }
    
        public static class InternalUtils{
    
            public static void sendEmail(String from, String[]  to, String msg, String body){
    
            }
    
        }
    
        public class Order{
    
            public boolean isSuccessful(){
                return true;
            }
    
        }
    
    }
    

    因为它调用了两次,所以你只需要更改 verify(times(2))... 就可以了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      相关资源
      最近更新 更多