我讨厌将单元测试引入到旧版代码库中,但是我必须这样做。
到目前为止,我已经使用Mockito和PowerMock成功地将单元测试引入了旧代码库。在遇到这种情况之前,效果非常好:


在SUT中,有几个静态变量(我在PowerMock的帮助下进行了模拟,模拟了静态方法和模拟构造函数)。
现在,在第一个测试方法中,所有方法都工作正常,并且模拟的静态var返回了预期的输出值。
但是在随后的测试方法中,模拟的静态对象始终返回在第一个测试中设置的值,尽管我在测试之前确实对它调用过reset()。

// legacy code base:
public class SUT {
  private static Collaborator1 c1 = null;
  private static Collaborator2 c2 = null;

  public SUT(param1) {
    if (c1 == null) {
        c1 = Collaborator1.instance(param1);
        c2 = new Collaborator2(c1);
    } else {
    }
  }
}



// newly introduced unit tests:
@RunWith(PowerMockRunner.class)
@PrepareForTest({
    SUT.class,                  // to mock: new Collaborator2(..), as required by PowerMock when mocking constructors
    Collaborator1.class,        // to mock: Collaborator1.instance(..), as required by PowerMock in mocking static methods
})
public class SUTTest {

  private SUT sut;

  private Collaborator1 c1 = mock(Collaborator1.class);
  private Collaborator2 c2 = mock(Collaborator2.class);

  @Before
  public void setup() {
    // mock c1:
    PowerMockito.mockStatic(Collaborator1.class);
    when(Collaborator1.instance(param1)).thenReturn(c1);

    // mock c2:
    PowerMockito.whenNew(Collaborator2.class).withArguments(c1).thenReturn(c2);

    reset(c1);
    reset(c2);

    sut = new SUT(param1);
  }

  @Test
  public void test1() {
    when(c2.foo(input1)).thenReturn(out1);

    // do something
  }

  @Test
  public void test2() {
    when(c2.foo(input2)).thenReturn(out2);    // BANG!!! c2.foo(input2) always return "out1"

    // do something
  }
}

由于SUT的构造函数仅在静态c1为null时实例化c1和c2,因此它们(c1,c2)不会在子序列调用中重新实例化。我不明白的是为什么reset(c1),reset(c2)在test2中不起作用?

任何想法?

最佳答案

终于成功了。基本上,我无法在两个不同的测试运行中设置 stub (模拟的静态实例变量)。我必须在第一个@Before中设置预期的行为。
因此,而不是使用

  @Before
  public void setup() {
    ...
  }

  @Test
  public void test1() {
    when(c2.foo(input1)).thenReturn(out1);
  }

  @Test
  public void test2() {
    when(c2.foo(input2)).thenReturn(out2);
  }

我应该使用以下顺序:
@Before
  public void setup() {
    when(c2.foo(input1)).thenReturn(out1);
    when(c2.foo(input2)).thenReturn(out2);
  }

  @Test
  public void test1() {
    // do something
  }

  @Test
  public void test2() {
    // do something
  }

PowerMock/Mockito有一些限制(错误?)?

关于java - Mockito/PowerMock : how to reset a mocked static variable in SUT?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5786749/

10-12 05:03