PowerMockito模拟间接静态方法

时间:2017-09-15 08:29:24

标签: java unit-testing junit mockito powermock

要测试的课程

public class Randomer {
    public int get() {
        return (int) Math.random() + 1;
    }
}

测试类

package org.samiron;

import static org.junit.Assert.assertEquals;

import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.api.support.membermodification.MemberMatcher;
import org.powermock.api.support.membermodification.MemberModifier;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.testng.annotations.Test;

/**
 * @author samiron
 *
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Randomer.class, Math.class })
public class RandomerTest {

    @Test
    public void shouldAddUpDieRollsCorrectly() throws Exception {
        PowerMockito.spy(Math.class);
        MemberModifier.stub(MemberMatcher.method(Math.class, "random")).toReturn(2.0);
        Randomer d = new Randomer();
        assertEquals(3, d.get());
    }
}

始终获得java.lang.AssertionError: expected:<3> but was:<1>

这里出了什么问题?说实话,每次遇到模拟静态函数的情况时,我都试图找到一种方法,而不是浪费时间。所以需要你的帮助来找出确切的解决方案。

示例类的唯一目的是证明Math.random()函数未被模拟,因此不返回所需的值。

一般实现

在编写测试时,模拟是一种必不可少的工具。尽管对实例的模拟工作与预期完全相同,但是模拟静态方法似乎是一个非常复杂的模拟库和许多选项的组合,以支持几个简单的场景。这应该简化。

使用的库:

  • 的Mockito-全1.9.5.jar
  • powermock-的Mockito离型全1.5.1 full.jar

2 个答案:

答案 0 :(得分:2)

此测试通过,从而证明静态调用Math.random() 已成功模拟:

@RunWith(PowerMockRunner.class)
// tell PowerMock about (a) the class you are going to test and (b) the class you are going to 'mock static'
@PrepareForTest({Randomer.class, Math.class })
public class RandomerTest {

    @Test
    public void shouldAddUpDieRollsCorrectly() throws Exception {
        // prepare PowerMock for mocking statics on Math
        PowerMockito.mockStatic(Math.class);
        // establish an expectation for what Match.random() should return
        PowerMockito.when(Math.random()).thenReturn(2.0);

        Randomer d = new Randomer();

        assertEquals(3, d.get());
    }
}

这与您在问题中发布的内容之间的主要区别在于我正在使用...

  • PowerMockito.mockStatic(Math.class)PowerMockito.when(Math.random()).thenReturn(2.0)

...而不是:

  • PowerMockito.spy(Math.class)MemberModifier.stub(MemberMatcher.method(Math.class, "random")).toReturn(2.0)

此外,在您的OP中,示例代码使用JUnit(org.powermock.modules.junit4.PowerMockRunner)和TestNG(org.testng.annotations.Test)的混合,而在我的示例中,我只使用JUnit。

上述内容已通过

验证
  • junit:4.12
  • powermock-module-junit4:1.7.0
  • powermock-api-mockito2:1.7.0

答案 1 :(得分:1)

这里似乎存在库不匹配。

在您声明的评论中使用以下依赖项(没有Maven的便利):

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-all</artifactId>
  <version>1.9.5</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-mockito-release-full</artifactId>
  <version>1.5.1</version>
  <scope>test</scope>
</dependency>

我的代码使用了这些代码:

<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-module-junit4</artifactId>
  <version>1.7.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito</artifactId>
  <version>1.7.0</version>
  <scope>test</scope>
</dependency>