Robolectric test cases of flavor A passes while fl

2019-07-17 01:46发布

问题:

My app contains two flavors of A and B. When I run ./gradlew app:test all tests of flavor A passes while flavor B fails. I also have two build types of debug and release.

My architecture is like this:

\my-project
---- \app
-------- \src
------------ \debug
------------ \flavor_A
------------ \main
------------ \flavor_B
------------ \test
---------------- \java
-------------------- \ com.my.main.package
------------------------ \ My_test_classes.java 
-------------------- \ TestApplication.java

TestApplication.java overrides some methods that has been defined in man Application class, as explained here.

My test class is very simple.

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21, packageName = "com.my.main.package")
public class WelcomeActivityTest
{
    Activity activity;
    Button btnSignUp;
    TextView btnSkip;

    @Before
    public void setUp()
    {
        activity = Robolectric.buildActivity(WelcomeActivity.class).create().get(); // << line 32

        btnSignUp = (Button) activity.findViewById(R.id.dialog_welcome_sign_up);
        btnSkip = (TextView) activity.findViewById(R.id.dialog_welcome_next_time);
    }

    @Test
    public void shouldNotBeNull() throws Exception
    {
        assertNotNull(activity);
    }

    @Test
    public void shouldHaveSignUp_SkipButtons() throws Exception {
        assertViewIsVisible(btnSignUp);
        assertViewIsVisible(btnSkip);
    }

    public static void assertViewIsVisible(View view) {
        assertNotNull(view);
        assertThat(view.getVisibility(), equalTo(View.VISIBLE));
    }
}

finally, this is the log that I'm getting:

java.util.ConcurrentModificationException
    at java.util.ArrayList.sort(ArrayList.java:1456)
    at java.util.Collections.sort(Collections.java:141)
    at org.robolectric.res.ResBundle.put(ResBundle.java:32)
    at org.robolectric.res.ResBunch.put(ResBunch.java:12)
    at org.robolectric.res.ValueResourceLoader.processNode(ValueResourceLoader.java:36)
    at org.robolectric.res.XpathResourceXmlLoader.processResourceXml(XpathResourceXmlLoader.java:22)
    at org.robolectric.res.ValueResourceLoader.processResourceXml(ValueResourceLoader.java:19)
    at org.robolectric.res.XmlLoader.processResourceXml(XmlLoader.java:46)
    at org.robolectric.res.DocumentLoader.loadResourceXmlFile(DocumentLoader.java:47)
    at org.robolectric.res.DocumentLoader.loadFile(DocumentLoader.java:40)
    at org.robolectric.res.DocumentLoader.load(DocumentLoader.java:30)
    at org.robolectric.res.PackageResourceLoader.loadEverything(PackageResourceLoader.java:32)
    at org.robolectric.res.PackageResourceLoader.doInitialize(PackageResourceLoader.java:19)
    at org.robolectric.res.XResourceLoader.initialize(XResourceLoader.java:29)
    at org.robolectric.res.XResourceLoader.getValue(XResourceLoader.java:52)
    at org.robolectric.res.PackageResourceLoader.getValue(PackageResourceLoader.java:5)
    at org.robolectric.res.RoutingResourceLoader.getValue(RoutingResourceLoader.java:31)
    at org.robolectric.shadows.ShadowAssetManager.resolveStyle(ShadowAssetManager.java:343)
    at org.robolectric.shadows.ShadowAssetManager.applyThemeStyle(ShadowAssetManager.java:286)
    at org.robolectric.shadows.ShadowResources$ShadowTheme.applyStyle(ShadowResources.java:461)
    at android.content.res.Resources$Theme.applyStyle(Resources.java)
    at android.app.ContextImpl.getTheme(ContextImpl.java:838)
    at android.content.ContextWrapper.getTheme(ContextWrapper.java:121)
    at android.view.ContextThemeWrapper.initializeTheme(ContextThemeWrapper.java:135)
    at android.view.ContextThemeWrapper.setTheme(ContextThemeWrapper.java:85)
    at org.robolectric.shadows.ShadowActivity.setThemeFromManifest(ShadowActivity.java:85)
    at org.robolectric.shadows.CoreShadowsAdapter$1.setThemeFromManifest(CoreShadowsAdapter.java:35)
    at org.robolectric.util.ActivityController.attach(ActivityController.java:58)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:121)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:304)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:45)
    at org.robolectric.util.ActivityController.create(ActivityController.java:118)
    at org.robolectric.util.ActivityController.create(ActivityController.java:129)
    at com.passenger.WelcomeActivityTest.setUp(WelcomeActivityTest.java:32)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)


Process finished with exit code 255

The thing that has confused me is I'm not different test for flavors so why tests of flavorA passes while flavorB fails.

回答1:

It seems I fixed my issue.

My problem was lack of deep understanding of build variants. I thought if I have TestApplication.java under test folder then its contents applies to both debug and release however it just applies to release.

I changed its name to TestDebugApplication and copied to debug folder and problem fixed.



回答2:

This was an issue with multiple threads accessing resources, causing Robolectric to attempt to load the resources concurrently.

I fixed this in https://github.com/robolectric/robolectric/pull/2353. If you use the latest snapshot, it should work, or you can wait for the 3.1 release.

As a temporary measure, if you just force loading a resource in Application#onCreate() or some other method that will be run before any additional threads are created, it will ensure the resources have been loaded before multiple threads try to use them.

I suspect whatever you changed resulted in this happening, which would have masked the error, as this has nothing to do with build variants.