2015-10-06 106 views
3

为什么我的单元测试在独立运行时通过,但在运行多个测试时失败?PowerMock测试通过然后失败

当我执行单个单元测试时,我的测试将成功模拟并返回预期结果。但是,当我运行所有单元测试时,先前通过的测试将失败。

一次测试运行

shouldDoThisAgain() - 通过

多重测试运行

shouldDoThis() - 通过

shouldDoThisAgain() - 失败

shouldDoThisAgainAgain() - 失败

我的测试:

@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; 
    } 
} 
+0

你的'OtherMethods'特别是'getDal()'的实现是非常糟糕的主意。 –

回答

4

我找到了我们项目的解决方案。我编写了一个调用Android内部静态日志方法的Logger类。我的一些测试没有直接测试Log类。当我忽略所有这些,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() { 
     // ... 
    } 

} 

现在的测试是绿色的一次。耶为非片状测试! :)

+0

与Powermock + easymock + junit类似的情况。也只有第一次测试成功了。在每次测试帮助之前将{@PrepareForTest}移至。但是要这样呢?是不是PowerMock中的某种错误? – murison

1

检查什么的@PrepareForTest({OtherMethods.class})时的行为置于一流水平...

已被删除以回应OP的评论
我只注意到别的东西:
我相信,你的MyWrapper类是Runnable,因此它只能run()一次,就需要重新初始化它为每个测试
删除

编辑: 然后您的问题是在您的实施OtherMethods类,你不显示它在这里,这使我们很难

+0

对不起,它不可运行,我的坏。我试图将它推广为一个被执行的函数。 – Angelito

+0

你说得对,它是在我的OtherMethods类的实现中。很好。我没有在原始文章中正确引用代码。我修改了问题发生的方式。基本上,我在我的'OtherMethods.class'中对我的dal进行了单例模拟。但是,在我的测试中,我引用了本地'dalMock'对象,而不是RuleMethods中的模拟对象。我受过教育的猜测是我指的是错误的对象。非常感谢。 – Angelito

+0

作为一个方面说明:当你找到有用的答案或评论时,标记/标记它们是有用的... –

0

尝试这样做

@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()); 
} 
} 
+0

我做到了。它仍然重复相同的行为(假设我在每个@Test中更改了'List results')。 – Angelito

+0

您不必重复when(OtherMethods.getDal()。getResults())。然后返回(结果);每次更改结果时都会声明。只需使用.then返回(results1),然后返回(results2)等。既然你正在测试! results.isEmpty()在每个方法中,您可以将这三个assertTrues放入一个测试方法中。不需要三种独立的方法 – 2015-10-06 18:47:07

相关问题