PowerMock 测试通过然后失败
PowerMock test passes then fails
为什么我的单元测试在 运行 独立时通过,但在 运行 多个测试时失败?
当我执行单个单元测试时,我的测试将成功模拟并 return 预期结果。但是,当我 运行 所有单元测试时,我之前通过的测试都将失败。
一次测试运行
shouldDoThisAgain() - Pass
多次测试运行秒
shouldDoThis() - Pass
shouldDoThisAgain() - Fail
shouldDoThisAgainAgain() - Fail
我的测试:
@PrepareForTest({OtherMethods.class})
@PowerMockIgnore("javax.management.*")
@RunWith(PowerMockRunner.class)
public class DbTest {
@Test
public void shouldDoThis() throws Exception() {
Dal dalMock = mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
List<Result> results = new ArrayList<Result>();
results.add(new Result(1,2,3));
when(dalMock.getResults()).thenReturn(results)
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgain() throws Exception() {
Dal dalMock = mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
List<Result> results = new ArrayList<Result>();
results.add(new Result(2,3,4));
when(dalMock.getResults()).thenReturn(results)
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgainAgain() throws Exception() {
Dal dalMock = mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
List<Result> results = new ArrayList<Result>();
results.add(new Result(6,5,3));
when(dalMock.getResults()).thenReturn(results)
assertTrue(Wrapper.MY_WRAPPER.run());
}
}
我的类:
public class Wrapper {
// not Runnable
public static final MyWrapper MY_WRAPPER = new MyWrapper(...){
@Override
public boolean run() {
// returns empty list when the test is alone
// returns 'results' variable when ran with other tests alone
List<Result> results = OtherMethods.getDal().getResults();
return !results.isEmpty()
}
};
}
public class OtherMethods {
private static final Logger LOGGER = LogManager.getLogger(OtherMethods.class);
public static Dal dal;
static Dal getDal() {
if (dal == null) {
try {
dal = new Dal();
} catch (Exception e) {
LOGGER.fatal("DB Connection could not be created for Geonames");
LOGGER.fatal(e);
}
}
return dal;
}
}
检查 @PrepareForTest({OtherMethods.class})
放置在 class 水平时的行为...
已删除以回应 OP 的评论
我刚刚注意到其他事情:
我假设你的 MyWrapper
class 是 Runnable
因此它只能 run()
一次,你需要为每个测试重新初始化它
已删除
编辑:
那么你的问题出在你的OtherMethods
class实现上,你没有在这里显示,这给我们造成了困难
尝试这样做
@PrepareForTest({OtherMethods.class})
@PowerMockIgnore("javax.management.*")
@RunWith(MowerMockRunner.class)
public class DbTest {
@Before
public void setUp(){
Dal dalMock = mock(Dal.class);
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock);
List<Result> results = new ArrayList<Result>();
results.add(new Result(1,2,3));
when(OtherMethods.getDal().getResults()).thenReturn(results)
}
@Test
public void shouldDoThis() throws Exception() {
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgain() throws Exception() {
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgainAgain() throws Exception() {
assertTrue(Wrapper.MY_WRAPPER.run());
}
}
我找到了我们项目的解决方案。我写了一个 Logger class 调用 Android 的内部静态 Log 方法。我的一些测试没有直接测试Log class。当我忽略所有这些时,基于 powermockito 的测试变为绿色。但是当这些其他测试是 运行 时,基于 powermockito 的测试将失败。有时候。
这种方法会失败(不稳定):
@RunWith(PowerMockRunner.class)
@PrepareForTest({Log.class}) // WARNING: HERE BE DRAGONS!
public class MyTest {
@Test
public void testMethodThatDoesNotUseStatics() {
// ...
}
@Test
public void usesStatics() {
// ...
}
}
然后我发现你可以用@PrepareForTest
注释每个测试方法,像这样:
@RunWith(PowerMockRunner.class)
public class MyTest {
@Test
public void testMethodThatDoesNotUseStatics() {
// ...
}
@Test
@PrepareForTest({Log.class}) // that's the way :)
public void usesStatics() {
// ...
}
}
现在测试又变绿了。是的,非易碎测试! :)
为什么我的单元测试在 运行 独立时通过,但在 运行 多个测试时失败?
当我执行单个单元测试时,我的测试将成功模拟并 return 预期结果。但是,当我 运行 所有单元测试时,我之前通过的测试都将失败。
一次测试运行
shouldDoThisAgain() - Pass
多次测试运行秒
shouldDoThis() - Pass
shouldDoThisAgain() - Fail
shouldDoThisAgainAgain() - Fail
我的测试:
@PrepareForTest({OtherMethods.class})
@PowerMockIgnore("javax.management.*")
@RunWith(PowerMockRunner.class)
public class DbTest {
@Test
public void shouldDoThis() throws Exception() {
Dal dalMock = mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
List<Result> results = new ArrayList<Result>();
results.add(new Result(1,2,3));
when(dalMock.getResults()).thenReturn(results)
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgain() throws Exception() {
Dal dalMock = mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
List<Result> results = new ArrayList<Result>();
results.add(new Result(2,3,4));
when(dalMock.getResults()).thenReturn(results)
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgainAgain() throws Exception() {
Dal dalMock = mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
List<Result> results = new ArrayList<Result>();
results.add(new Result(6,5,3));
when(dalMock.getResults()).thenReturn(results)
assertTrue(Wrapper.MY_WRAPPER.run());
}
}
我的类:
public class Wrapper {
// not Runnable
public static final MyWrapper MY_WRAPPER = new MyWrapper(...){
@Override
public boolean run() {
// returns empty list when the test is alone
// returns 'results' variable when ran with other tests alone
List<Result> results = OtherMethods.getDal().getResults();
return !results.isEmpty()
}
};
}
public class OtherMethods {
private static final Logger LOGGER = LogManager.getLogger(OtherMethods.class);
public static Dal dal;
static Dal getDal() {
if (dal == null) {
try {
dal = new Dal();
} catch (Exception e) {
LOGGER.fatal("DB Connection could not be created for Geonames");
LOGGER.fatal(e);
}
}
return dal;
}
}
检查 @PrepareForTest({OtherMethods.class})
放置在 class 水平时的行为...
已删除以回应 OP 的评论
我刚刚注意到其他事情:
我假设你的 MyWrapper
class 是 Runnable
因此它只能 run()
一次,你需要为每个测试重新初始化它
已删除
编辑:
那么你的问题出在你的OtherMethods
class实现上,你没有在这里显示,这给我们造成了困难
尝试这样做
@PrepareForTest({OtherMethods.class})
@PowerMockIgnore("javax.management.*")
@RunWith(MowerMockRunner.class)
public class DbTest {
@Before
public void setUp(){
Dal dalMock = mock(Dal.class);
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock);
List<Result> results = new ArrayList<Result>();
results.add(new Result(1,2,3));
when(OtherMethods.getDal().getResults()).thenReturn(results)
}
@Test
public void shouldDoThis() throws Exception() {
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgain() throws Exception() {
assertTrue(Wrapper.MY_WRAPPER.run());
}
@Test
public void shouldDoThisAgainAgain() throws Exception() {
assertTrue(Wrapper.MY_WRAPPER.run());
}
}
我找到了我们项目的解决方案。我写了一个 Logger class 调用 Android 的内部静态 Log 方法。我的一些测试没有直接测试Log class。当我忽略所有这些时,基于 powermockito 的测试变为绿色。但是当这些其他测试是 运行 时,基于 powermockito 的测试将失败。有时候。
这种方法会失败(不稳定):
@RunWith(PowerMockRunner.class)
@PrepareForTest({Log.class}) // WARNING: HERE BE DRAGONS!
public class MyTest {
@Test
public void testMethodThatDoesNotUseStatics() {
// ...
}
@Test
public void usesStatics() {
// ...
}
}
然后我发现你可以用@PrepareForTest
注释每个测试方法,像这样:
@RunWith(PowerMockRunner.class)
public class MyTest {
@Test
public void testMethodThatDoesNotUseStatics() {
// ...
}
@Test
@PrepareForTest({Log.class}) // that's the way :)
public void usesStatics() {
// ...
}
}
现在测试又变绿了。是的,非易碎测试! :)