java - 每个 @InjectMocks 调用都没有考虑 PowerMock 静态方法模拟

标签 java unit-testing mockito junit4 powermock

我想编写一些使用 JUnit 4.12、Mockito 1.9.5 和 PowerMock 1.6.1 的单元测试。 该类有一些字段用@Mock 注释,还有一些字段用@InjectMocks 注释。 用@InjectMocks 注释的属性在某个点到达父构造函数,其中包含一些静态方法调用,应该用 PowerMock 模拟。 问题是第一个测试无缝运行,而第二个测试似乎根本没有模拟静态方法。

@RunWith(PowerMockRunner.class)
@PrepareForTest({ StaticClass.class })
public class TestClass {
  @Mock
  private SomeClass attribute1;
  @InjectMocks
  private SomeOtherClass attribute2;

  @BeforeClass
  public static void setUp() {
    PowerMockito.mockStatic(StaticClass.class);

 when(StaticClass.staticMethod(any(), any()).thenReturn(new SomeConcreteClass());
  }

  @Test
  public void test1() {
    assertEquals(attribute2.method1(), value1);
  }

  @Test
  public void test2() {
    assertEquals(attribute2.method2(), value2);
  }
}

public class SomeOtherClass {
  private SomeClass attribute;
  public SomeOtherClass() {
    SomeConcreteClass value = StaticClass.staticMethod(argument1, argument2);
    value.someOtherMethod();
  }
}

如前所述,第一个测试通过并且 StaticClass.staticMethod() 被 PowerMock 预期的模拟。 第二个测试没有通过,当对值调用 someOtherMethod 时,它在行中抛出 NullPointerException(因为 value = null,因为 PowerMock 不再模拟 StaticClass.staticMethod)。

最佳答案

如 ( Mocking behaviour resets after each test with PowerMock) 中所述,Powermock 在每次测试前重置模拟。

出于某种原因,它第一次起作用 - 存在 该问题的未解决错误报告 ( https://github.com/powermock/powermock/issues/398 )。


它的设计可以说是糟糕的,但可以按照以下方式做你想做的事情:
不要依赖注释,而是手动设置模拟。

private SomeClass attribute;
private SomeOtherClass testClass;

@Before
public void setUp() {
    PowerMockito.mockStatic(StaticClass.class);
    Mockito.when(StaticClass.staticMethod(anyString())).thenReturn(new SomeConcreteClass());

    attribute = Mockito.mock(SomeClass.class);      
    testClass = new SomeOtherClass();

    // assign mock manually
    testClass.attribute = attribute;
}

首选方法是使用 SomeOtherClass 的构造函数提供 attribute
但是因为您似乎使用了一个空构造函数 您将不得不从外部设置值。
如果 attribute 实例不可访问,您可能被迫使用反射。


更简洁的方法是重构 SomeOtherClass 的构造函数,使其不在内部使用静态方法。将 SomeConcreteClass 作为参数传递给构造函数是可行的方法。

有些人甚至说你不应该在构造函数中包含任何逻辑。

关于java - 每个 @InjectMocks 调用都没有考虑 PowerMock 静态方法模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57291615/

相关文章:

java - Java 解析 JSON 时出错 : ClassNotFoundException

java - IntelliJ Idea "entry point annotations"设置保存在哪里?

c# - 如何测试返回的数组至少包含一个具有特定属性值的值

java - 是否可以使用 Sikuli 进行 JUnit 测试并在失败时截取屏幕截图?

java - 如何使用构造函数注入(inject)模拟类

java - 在 Spring Boot 应用程序中使用 Mockito

java - Android Studio fragment

java - Netty过滤反向代理

javascript - Jasmine 无法实例化 Angular 模块?

java - 如何在 JUnit 测试中强制 Mockito 抛出 RemoteException