每次@InjectMocks调用均不考虑PowerMock静态方法模拟

时间:2019-07-31 13:13:08

标签: 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();
  }
}

如前所述,第一个测试通过,并且PowerMock按预期模拟了StaticClass.staticMethod()。 在值上调用someOtherMethod时,第二项测试未通过,并且在行上引发NullPointerException(因为value = null,因为PowerMock不再模拟StaticClass.staticMethod)。

1 个答案:

答案 0 :(得分:1)

如(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;
}

首选方式是使用attribute的构造函数提供SomeOtherClass
但是,由于您似乎使用了空的构造函数 您将必须从外部设置该值。
如果无法访问attribute实例,则可能被迫使用反射。


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

甚至有人说您不应在构造函数内部包含任何逻辑。