Powermock:仍然调用模拟方法

时间:2014-06-18 09:29:19

标签: java unit-testing junit4 powermock

首先,请知道我在问这个问题之前已经搜索过了,但我找不到令人满意的答案。

我正在使用JUnit4和Powermock 1.5.5(使用mockito 1.9.5)

我的问题如下:在我的单元测试中,我需要在一个我无法修改的类中模拟一个静态方法。我只想模仿一种方法,而不是全班,所以我去找间谍。

这是我到目前为止所拥有的:

[...]
import static org.mockito.Matchers.*;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(JUnitParamsRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext-test.xml"},
    loader=MockWebApplicationContextLoader.class)
@MockWebApplication(name="my-app")
@PrepareForTest(value = {
    Role.class
})
public class MyTest {

    @Rule
    public PowerMockRule powerMockRule = new PowerMockRule();

    @Before
    public void setUp() throws Exception {
        initSpring();
        mockRoleServices();
    }

    private void mockRoleServices() throws Exception {
        spy(Role.class);
        RoleAnswer roleAnswer = new RoleAnswer(RoleEnum.ADMIN);
        when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
            .then(roleAnswer);
    }

    private class RoleAnswer implements Answer<Boolean> {

        private RoleEnum roleEnum;

        private RoleAnswer(RoleEnum roleEnum) {
            this.roleEnum = roleEnum;
        }

        @Override
        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            return getRenderRequest().getUserRole() != null &&
                    getRenderRequest().getUserRole().equals(roleEnum);
        }
    }
}

问题在于:方法Role.hasAdministratorRole()被调用而不是被模拟

这是我到目前为止所尝试的内容:

  • 使用mockStatic(Role.class)代替spy()方法。正如预期的那样,所有方法都被模拟,所以我在调用Role.hasAdministratorRole()
  • 之前最终获得了NPE
  • doAnswer(...).when(...)之类的事情。我发现powermock的运行时错误告诉我我的模拟不完整(这实际上证实了我的代码或lib本身的错误)
  • 尝试按名称声明方法,而不是直接调用它:when(Role.class, "hasAdministratorRole", long.class, long.class, long.class)。相同的行为
  • 我不记得了其他一些事情。

非常感谢您的帮助。 谢谢!

编辑:感谢SrikanthLingala的回答,我能够找出问题所在。

这不起作用:

when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
    .thenAnswer(roleAnswer);

但是这样做了:

doAnswer(roleAnswer).when(Role.class, "hasSiteAdministratorRole",
    anyLong(), anyLong(), anyLong());

然后切换when()answer()工作

2 个答案:

答案 0 :(得分:2)

由于我没有完成所有实现,因此我设置了一些虚拟实现,并进行了与您类似的设置。以下代码适用于我。

import static junit.framework.Assert.assertTrue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(value = {
    Role.class
})
public class RoleTest {

    @Test
    public void mockRoleServices() throws Exception {
        PowerMockito.spy(Role.class);
        PowerMockito.doAnswer(new RoleAnswer(RoleEnum.ADMIN)).when(Role.class, "hasAdministratorRole", Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());

        Role.printOut();

        assertTrue(Role.hasAdministratorRole(1, 1, 1));
    }

    private class RoleAnswer implements Answer<Boolean> {

        private RoleEnum roleEnum;

        private RoleAnswer(RoleEnum roleEnum) {
            this.roleEnum = roleEnum;
        }

        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            return true;
        }
    }
}

虚拟角色类:

public class Role {

    public static Boolean hasAdministratorRole(long a, long b, long c) {
        System.out.println("Inside hasAdministratorRole");
        return a + b + c < 0;
    }

    public static void printOut() {
        System.out.println("Inside Printout");
    }

}

我的测试用例不打印Inside hasAdministratorRole,但打印出Inside Printout

希望这有帮助

答案 1 :(得分:1)

很高兴你已经解决了你的问题,这只是对其他人有类似问题的警告。

项目设置:

  • Powermock 1.5.5
  • Mockito 1.9.5
  • TestNG 6.8.8

Powermock未考虑使用 @BeforeTest

注释的方法中创建的模拟/间谍

E.g:

@BeforeTest
public void setup(){
    testee = mock(AClass.class);
}

它被丢弃然后它进入模拟方法而不是返回预期结果或抛出各种奇怪的异常。当转移到一个通用的测试方法时,它突然开始工作:

@Test
public void test(){
    AClass testee = mock(AClass.class);
    ....
}

可能是一个错误。

相关问题