首页 > 解决方案 > PowerMockito 在定义第二个“when”子句时调用 Mocked Object 上的真实方法

问题描述

当使用不同的参数调用方法时,我试图定义一些不同的模拟行为。不幸的是,我发现第二次尝试在(模拟)类上模拟给定方法时,它运行实际方法,导致异常,因为匹配器不是有效参数。任何人都知道我可以如何防止这种情况?

    manager = PowerMockito.mock(Manager.class);
    try {
        PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
                .thenReturn(manager);
    } catch (Exception e) {
        e.printStackTrace();
    }
    FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);
    PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
    PowerMockito.when(manager.createFindAuthorityDescriptionRequest(Matchers.eq(VALID_IK),
            Matchers.eq(VALID_CATEGORY_NAME))).thenReturn(validFindAuthorityDescription);
    PowerMockito.when(manager.processRequest(Matchers.any(FindAuthorityDescriptionRequest.class)))
            .thenThrow(ManagerException.class);
    PowerMockito.when(manager.processRequest(Matchers.eq(validFindAuthorityDescription)))
            .thenReturn(generateValidAuthorityDescriptionResponse());

标签: mockitopowermockitocase-whenspringmockito

解决方案


以下代码是基于您的模拟设置的工作示例(我添加了虚拟类以使其可运行)。

该代码还包含用于验证模拟方法是否返回预期值的断言。此外,真正的方法createFindAuthorityDescriptionRequest只被调用一次。


注意:这是用 `powermock 2.0.7` 和 `mockito 2.21.0` 测试的。

如果问题仍然存在,我建议检查是否没有从程序中的其他地方额外调用真正的方法(除了问题陈述中引用的代码)。

package com.example.stack;

import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.*;
import static org.powermock.api.mockito.PowerMockito.mock;

@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.example.stack.*")
public class StackApplicationTests {

    private static final String VALID_IK = "IK";
    private static final String VALID_CATEGORY_NAME = "CATEGORY_NAME";
    private static final Object VALID_RESPONSE = "RESPONSE";

    @Test
    public void test() {
        Manager manager = mock(Manager.class);
        try {
            PowerMockito.whenNew(Manager.class).withArguments(anyString(), anyString())
                    .thenReturn(manager);
        } catch (Exception e) {
            e.printStackTrace();
        }

        FindAuthorityDescriptionRequestImpl validFindAuthorityDescription = mock(FindAuthorityDescriptionRequestImpl.class);

        PowerMockito.when(manager.createFindAuthorityDescriptionRequest(anyString(), anyString())).thenCallRealMethod();
        PowerMockito.when(manager.createFindAuthorityDescriptionRequest(eq(VALID_IK), eq(VALID_CATEGORY_NAME)))
                .thenReturn(validFindAuthorityDescription);
        PowerMockito.when(manager.processRequest(any(FindAuthorityDescriptionRequest.class)))
                .thenThrow(ManagerException.class);
        PowerMockito.when(manager.processRequest(eq(validFindAuthorityDescription)))
                .thenReturn(VALID_RESPONSE);


        // verify that the mock returns expected results
        assertEquals(Manager.REAL_RESULT, manager.createFindAuthorityDescriptionRequest("any", "any"));
        assertEquals(validFindAuthorityDescription, manager.createFindAuthorityDescriptionRequest("IK", "CATEGORY_NAME"));

        assertThrows(ManagerException.class, new ThrowingRunnable(){
            @Override
            public void run( ) {
                manager.processRequest(new FindAuthorityDescriptionRequestImpl());
            }
        });

        assertEquals(VALID_RESPONSE, manager.processRequest(validFindAuthorityDescription));

    }

}

interface FindAuthorityDescriptionRequest {}
class FindAuthorityDescriptionRequestImpl implements FindAuthorityDescriptionRequest {}
class ManagerException extends RuntimeException {}

class Manager {
    
    public static FindAuthorityDescriptionRequestImpl REAL_RESULT = new FindAuthorityDescriptionRequestImpl();
    public Manager(String s1, String s2) {}

    public FindAuthorityDescriptionRequest createFindAuthorityDescriptionRequest(String ik, String category) {
        return REAL_RESULT;
    }

    public Object processRequest(FindAuthorityDescriptionRequest request) {
        return null;
    }
}

推荐阅读