2016-06-07 50 views
4

我目前繼承了一個Android應用程序,其代碼覆蓋率爲零,我的第一份工作是爲它編寫一些單元測試。所以我決定把它作爲學習Robolectric的機會。Robolectric - 應用程序在設置中有單身人士,導致測試問題

但是我碰到的初始問題得到兩個簡單的虛擬測試運行。

這是我在我的測試文件中的代碼:

@Config(constants = BuildConfig.class) 
@RunWith(RobolectricGradleTestRunner.class) 
public class SplashActivityTest { 

private SplashActivity activity; 

// @Before => JUnit 4 annotation that specifies this method should run before each test is run 
// Useful to do setup for objects that are needed in the test 
@Before 
public void setup() { 
    // Convenience method to run SplashActivity through the Activity Lifecycle methods: 
    // onCreate(...) => onStart() => onPostCreate(...) => onResume() 
    activity = Robolectric.setupActivity(SplashActivity.class); 
} 

// @Test => JUnit 4 annotation specifying this is a test to be run 
// Checking that the UI gets setup correctly 
@Test 
public void dummy() { 
    String test = "POP!"; 

    assertTrue("POP!", 
      test.equals("POP!")); 
} 

@Test 
public void dummyTwo() { 

    String test = "POP!!"; 

    assertTrue("POP!!", 
      test.equals("POP!!")); 
} 

} 

問題是活動擴展了另一個類稱爲baseactivity在這個類的自定義應用程序類使用。

在畢加索使用下面的代碼作爲一個Singleton創建了這個自定義應用程序類:

picasso = new Picasso.Builder(getApplicationContext()).downloader(new OkHttpDownloader(picassoClient)).build(); 
    Picasso.setSingletonInstance(picasso); 

當我跑我得到以下錯誤測試:

java.lang.IllegalStateException: Singleton instance already exists. at com.squareup.picasso.Picasso.setSingletonInstance(Picasso.java:677)

所以它看起來像應用程序類創建兩次,每次測試一次,如同一次測試,它運行良好。所以我假設我的測試模式在這裏是錯誤的?任何人都可以用正確的模式幫助我嗎?與單元測試一樣,我只想測試有限的功能,所以我不確定我在做什麼是正確的。

編輯:我試圖設置一個「模擬」應用程序類,並獲得Robolectric使用它,但它似乎仍然使用真正的應用程序類。

所以在測試/ java中我有下面的類:

public class TestMyApplication extends MyApplication 
     implements TestLifecycleApplication { 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     initPicasso(); 
    } 

    @Override 
    protected void initPicasso() { 
     //nothing to do 
    } 

    @Override public void beforeTest(Method method) { 
    } 

    @Override public void prepareTest(Object test) { 
    } 

    @Override public void afterTest(Method method) { 
    } 
} 

正如你可以看到它擴展了所有MyApplication類,這是在我的主應用程序,我還增加了@Override到initPicasso方法嘗試以阻止它被調用,但是當我運行我的測試時,我仍然得到第二次測試中第二次設置畢加索單件的錯誤。

因此,當我運行我的測試類時,它仍然進入我的主應用程序中的Application類,爲什麼Robolectric在單元測試應該限制在範圍內時會這樣做?

我也試過這樣:

@Config(constants = BuildConfig.class, application = TestMyApplication.class) 

但是當我嘗試這一點,並運行測試類我得到一個錯誤說,它不能找到TestMyApplication,所以它是一種撕裂我的頭髮問題,爲什麼Robolectric不會使用我的模擬應用程序類。

+1

http://stackoverflow.com/questions/36969659/robolectric-3-與無緯crashlytics/36980405#36980405 –

+0

@EugenMartynov - 我已經試過這種方法,下面這一點 - http://robolectric.org/custom-test-runner/ - 我仍然得到同樣的問題,它就像它忽略TestApplication class –

+1

如果您嘗試了這種方法,那麼您更改了什麼?它應該爲每個測試創建應用程序 - 單元測試應該是獨立和可重複的 –

回答

4

爲了得到它的工作,我不得不創建下面的類,它擴展了RobolectricGradleTestRunner並強制它使用TestMyApplication類。

public class TestRunner extends RobolectricGradleTestRunner { 

    public TestRunner(final Class<?> testClass) throws InitializationError { 
     super(testClass); 
    } 

    @Override 
    protected Class<? extends TestLifecycle> getTestLifecycleClass() { 
     return MyTestLifecycle.class; 
    } 

    public static class MyTestLifecycle extends DefaultTestLifecycle { 
     @Override 
     public Application createApplication(final Method method, final AndroidManifest appManifest, final Config appConfig) { 
      // run tests under our TestApplication 
      return new TestMyApplication(); 
     } 
    } 

} 

然後在TestMyApplication類,我不得不重寫initPicasso方法:

@Override protected void initPicasso(){ 
     //do nothing 
    } 

只有這樣做Robolectric終於跳過initPicasso主MyApplication.java下課。

+2

它仍然應該開箱即用:)如果你可以共享代碼,我可能會得到它的修復,至少我願意:) –

+0

我會嘗試把它的一些樣本,當我有機會,併發送它對你來說,我無法分享這個特定的代碼。 –

+0

請保留風味並反映其中的應用程序ID更改 –

2

In Robolectric 3.4。2,在測試中使用自定義應用程序類的工作:

public class MyApplication extends Application { 

    protected void initPicasso() { 
     // do Picasso initialization 
    } 

} 

public class TestMyApplication extends MyApplication { 

    @Override 
    protected void initPicasso() { 
     //nothing to do 
    } 

} 

就在你的測試類增加一個配置註釋:

@Config(constants = BuildConfig.class, application = TestMyApplication.class)