Mockito/PowerMock:如何在 SUT 中重置模拟静态变量?
我讨厌将单元测试引入遗留代码库,但我必须这样做。
到目前为止,我使用 Mockito 和 PowerMock 成功地将单元测试引入到遗留代码库中。工作得很好,直到我遇到这种情况:
在SUT中,有几个静态变量(我在PowerMock的帮助下模拟了它们,模拟静态方法和模拟构造函数)。
现在在第一个测试方法中,一切正常,并且模拟的静态变量返回了预期的输出值。
但是在后续的测试方法中,模拟的静态对象总是返回在第一个测试中设置的值,尽管我在测试之前确实对其调用了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中没有效果?
有什么想法吗?
I hate to introduce Unit-tests into a legacy code base, but I have to.
Up untill now I successfully introduced unit-testing into the legacy code base using Mockito and PowerMock. Worked perfectly well until I met with this situation:
in the SUT, there're several static varibles (which I mocked with the help of PowerMock, mocking static methods and mocking constructors).
Now in the first test method, all worked fine and the mocked static var returned the expected output value.
but in the subsequent test methods, the mocked static object always returns value that has been set in the first test, although I did call reset() on it before the tests.
// 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
}
}
Since the constructor of SUT only instantiates c1 and c2 if the static c1 is null, they (c1, c2) don't get re-instantiated in sub-sequence calls. What I don't understand is why reset(c1), reset(c2) have no effect in test2?
Any idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
终于可以工作了基本上,我无法在两个不同的测试运行中设置存根(模拟的静态实例变量)。我必须在第一个@Before 中设置预期的行为。
而不是使用
因此,我应该使用以下序列
: PowerMock/Mockito 中的一些限制(错误?)?
Got it work finally. Basically, I can't set the stub (the mocked static instance variable) in two different test runs. I have to setup the expected behavior in the first @Before.
So instead of using
I should use this sequence:
Some limitation(bug?) in PowerMock/Mockito?
如果您使用 Mockito 来模拟静态方法,则需要
try (MockedStaticutilities = Mockito.mockStatic(StaticUtils.class)) {
)If you are using Mockito to mock static methods, you need to either
try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
)utilities.close()
)尝试将静态模拟设置移动到 @BeforeClass 设置方法,但将 Reset(mocks) 调用保留在测试 setup() 方法中。您只想设置您的mockStatic一次,但因为它们是静态的,所以您需要为每个测试重置它们,否则它们会与后续测试混淆。
即尝试
...
Try moving your static mock setup to an @BeforeClass setup method, but leave your reset(mocks) call in your test setup() method. You want to setup your mockStatic only once, but because they're static, you will want to reset them for every test or they'll muddle with subsequent tests.
i.e. try
...