2015-10-06 153 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

相關問題