Java PowerMock测试通过,然后失败
为什么我的单元测试在独立运行时通过,但在运行多个测试时失败 当我执行单个单元测试时,我的测试将成功模拟并返回预期结果。然而,当我运行所有单元测试时,我以前通过的测试将失败 一次试运行 shouldDothis()-通过 多次测试运行 shoulddotthis()-通过 shouldDothisArea()-失败 shouldDoThisAgainAgain()-失败 我的测试:Java PowerMock测试通过,然后失败,java,unit-testing,mocking,mockito,powermock,Java,Unit Testing,Mocking,Mockito,Powermock,为什么我的单元测试在独立运行时通过,但在运行多个测试时失败 当我执行单个单元测试时,我的测试将成功模拟并返回预期结果。然而,当我运行所有单元测试时,我以前通过的测试将失败 一次试运行 shouldDothis()-通过 多次测试运行 shoulddotthis()-通过 shouldDothisArea()-失败 shouldDoThisAgainAgain()-失败 我的测试: @PrepareForTest({OtherMethods.class}) @PowerMockIgnore(&qu
@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());
}
}
@PrepareForTest({OtherMethods.class})
@PowerMockIgnore(“javax.management.*”)
@RunWith(PowerMockRunner.class)
公共类DbTest{
@试验
public void shoulddotthis()引发异常(){
Dal dalMock=mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
列表结果=新建ArrayList();
结果。添加(新结果(1,2,3));
当(dalMock.getResults())。然后返回(results)
assertTrue(Wrapper.MY_Wrapper.run());
}
@试验
public void shoulddothisreach()引发异常(){
Dal dalMock=mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
列表结果=新建ArrayList();
结果。添加(新结果(2,3,4));
当(dalMock.getResults())。然后返回(results)
assertTrue(Wrapper.MY_Wrapper.run());
}
@试验
public void shouldDoThisAgainAgain()引发异常(){
Dal dalMock=mock(Dal.class)
PowerMockito.whenNew(Dal.class).withAnyArguments().thenReturn(dalMock)
列表结果=新建ArrayList();
结果。添加(新结果(6,5,3));
当(dalMock.getResults())。然后返回(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;
}
}
公共类包装器{
//无法运行
公共静态最终MyWrapper MY_WRAPPER=新MyWrapper(…){
@凌驾
公共布尔运行(){
//当测试单独进行时,返回空列表
//单独与其他测试一起运行时返回“results”变量
List results=OtherMethods.getDal().getResults();
return!results.isEmpty()
}
};
}
公共类方法{
私有静态最终记录器Logger=LogManager.getLogger(OtherMethods.class);
公共静态Dal;
静态Dal getDal(){
如果(dal==null){
试试{
dal=新的dal();
}捕获(例外e){
LOGGER.fatal(“无法为Geonames创建DB连接”);
致命的(e);;
}
}
返回dal;
}
}
检查@PrepareForTest({OtherMethods.class})
放置在类级别时的行为
针对OP的评论删除了我注意到了另外一件事:
我假设您的
MyWrapper
类是Runnable
,因此它只能run()
一次,您需要为每个测试重新初始化它已删除 编辑: 那么您的问题是在您的
其他方法的实现中
类,您没有在这里显示它,这使得我们很难尝试这样做
@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());
}
}
@PrepareForTest({OtherMethods.class})
@PowerMockIgnore(“javax.management.*”)
@RunWith(MowerMockRunner.class)
公共类DbTest{
@以前
公共作废设置(){
Dal-dalMock=mock(Dal.class);
PowerMockito.whenNew(Dal.class).withAnyArguments()。然后返回(dalMock);
列表结果=新建ArrayList();
结果。添加(新结果(1,2,3));
当(OtherMethods.getDal().getResults())。然后返回(results)
}
@试验
public void shoulddotthis()引发异常(){
assertTrue(Wrapper.MY_Wrapper.run());
}
@试验
public void shoulddothisreach()引发异常(){
assertTrue(Wrapper.MY_Wrapper.run());
}
@试验
public void shouldDoThisAgainAgain()引发异常(){
assertTrue(Wrapper.MY_Wrapper.run());
}
}
我为我们的项目找到了解决方案。我编写了一个Logger类,它调用Android的内部静态日志方法。我的一些测试没有直接测试Log类。当我忽略所有测试时,基于powermockito的测试变成绿色。但当这些其他测试运行时,基于powermockito的测试将失败。有时候
这种方法将失败(不可靠):
然后我发现你可以用@PrepareForTest
注释每个测试方法,如下所示:
@RunWith(PowerMockRunner.class)
public class MyTest {
@Test
public void testMethodThatDoesNotUseStatics() {
// ...
}
@Test
@PrepareForTest({Log.class}) // that's the way :)
public void usesStatics() {
// ...
}
}
现在测试又是绿色的。对非片状测试来说是的!:) 对不起,它不能运行,我的错。我试图将它概括为一个可以执行的函数。你是对的,这是我对OtherMethods类的实现。嗯,差不多。我在原来的帖子中没有正确引用代码。我根据问题是如何发生的修改了它。基本上,我在我的
OtherMethods.class
中对我的dal做了一个单例模拟。然而,在我的测试中,我引用了本地dalMock
对象,而不是RuleMethods中的mock对象。我的猜测是我指向了错误的对象。非常感谢。顺便说一句:当你发现有用的答案或评论时,标记/标记它们是很有用的……在我的“声誉”提高之前不能这么做。我做到了。它仍然复制相同的行为(假设我在每个@Test中更改列表结果
)。您不必重复when(OtherMethods.getDal().getResults())。然后返回(results);每次更改结果时都要使用语句。只需使用.thenReturn(results1)、thenReturn(results2)等等。既然你在测试这个!在每种方法中,您都可以将这三个AssertTrue放在一个测试方法中。不需要三种不同的方法您实现的其他方法
尤其是getDal()
是一个非常糟糕的主意。Powermock+easymock+junit也有类似的情况。也只有第一次测试成功。在每次测试之前将{@PrepareForTest}移动到有帮助。但肖卢德一世
@RunWith(PowerMockRunner.class)
public class MyTest {
@Test
public void testMethodThatDoesNotUseStatics() {
// ...
}
@Test
@PrepareForTest({Log.class}) // that's the way :)
public void usesStatics() {
// ...
}
}