17

I've created a new TestProject and added following line to my testMethod:

Robolectric.getShadowApplication().getString(R.string.mystring);

My test failed with

android.content.res.Resources$NotFoundException: unknown resource 2131558482

The console displays the following warnings:

WARNING: No manifest file found at .\..\..\MyProject\AndroidManifest.xml.Falling back to the Android OS resources only.
To remove this warning, annotate your test class with @Config(manifest=Config.NONE).
WARNING: no system properties value for ro.build.date.utc

Is AndroidManifest.xml necessary to get string resources? I tried to add Manifest by org.robolectric.Config.properties and @Config but the warning still occurs and I can't get string resource. I made sure the relative path to manifest is correct. I also tried changing the JUnit run configuration but this did not help.

swimfar
  • 147
  • 6
lukjar
  • 7,220
  • 2
  • 31
  • 40

7 Answers7

15

Solution to the problem described here: http://blog.futurice.com/android_unit_testing_in_ides_and_ci_environments

The Missing Manifest

You should have noticed by now that Robolectric complains about not being able to find your Android Manifest. We’ll fix that by writing a custom test runner. Add the following as app/src/test/java/com/example/app/test/RobolectricGradleTestRunner.java:

package com.example.app.test;

import org.junit.runners.model.InitializationError;
import org.robolectric.manifest.AndroidManifest;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.res.Fs;

public class RobolectricGradleTestRunner extends RobolectricTestRunner {
  public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
    super(testClass);
  }

  @Override
  protected AndroidManifest getAppManifest(Config config) {
    String myAppPath = RobolectricGradleTestRunner.class.getProtectionDomain()
                                                        .getCodeSource()
                                                        .getLocation()
                                                        .getPath();
    String manifestPath = myAppPath + "../../../src/main/AndroidManifest.xml";
    String resPath = myAppPath + "../../../src/main/res";
    String assetPath = myAppPath + "../../../src/main/assets";
    return createAppManifest(Fs.fileFromPath(manifestPath), Fs.fileFromPath(resPath), Fs.fileFromPath(assetPath));
  }
}

Remember to change the RunWith annotation in the test class.

Piotr Z
  • 864
  • 11
  • 11
user3635764
  • 166
  • 1
  • 4
  • 2
    Nice solution, but this doesn't work for me with Android Studio 1.1. Maybe the paths have changed since the support for unit testing. These paths worked for me: `String manifestPath = myAppPath + "../../../manifests/full/debug/AndroidManifest.xml"; String resPath = myAppPath + "../../../res/debug"; String assetPath = myAppPath + "../../../assets/debug";` – Rule Feb 22 '15 at 00:35
  • 1
    I really can't understan, why createAppManifest(...) method could not be resolved? What is missing? – SanchelliosProg Sep 24 '16 at 18:34
  • The futurice link is broken – Cris Sep 19 '18 at 08:34
8

I have faced same errors, We used several flavors and buildtypes So, there are steps to make it working:

1) Android studio tests run configuration

You have to set working directory to $MODULE_DIR$ in Windows too. http://robolectric.org/getting-started/ should say that.

2) Unit test should be annotated like this:

@RunWith(RobolectricTestRunner.class) 
@Config(constants = BuildConfig.class, sdk = 21, manifest = "src/main/AndroidManifest.xml", packageName = "com.example.yourproject") 
public class SomeFragmentTest {

Here we have plain link to manifest file and packageName

Kirill Vashilo
  • 1,559
  • 1
  • 18
  • 27
5

From the 4.0 version the use of @Config is not highly appreciated, however the updated Getting started guide solve my problem: http://robolectric.org/getting-started/

Only one build.gradle modification, and the Manifest file loaded, the tests can run.

android {
  testOptions {
    unitTests {
      includeAndroidResources = true
    }
  }
}

The related issue on github (also has been closed): https://github.com/robolectric/robolectric/issues/3328

Levente Takács
  • 435
  • 4
  • 15
  • you will also have to add `@Config(sdk = [Build.VERSION_CODES.O_MR1])` otherwise it will give error `Failed to create a Robolectric sandbox` – Zohab Ali May 17 '21 at 15:17
1

You need an AndroidManifest.xml and Robolectric currently depends on it being at the project root as the path implies.

Corey D
  • 4,689
  • 4
  • 25
  • 33
1

I noticed that I used to declare manifest like this at the top of my test class

@RunWith(RobolectricTestRunner.class)
@Config( constants = BuildConfig.class, manifest="app/src/main/AndroidManifest.xml", sdk = 21 )

And I switched now to this in order to work.

@RunWith(RobolectricTestRunner.class)
@Config( constants = BuildConfig.class, manifest="src/main/AndroidManifest.xml", sdk = 21 )
Juan Mendez
  • 2,658
  • 1
  • 27
  • 23
  • Do you have any idea why? Same code runs on two OS X machines, one is building properly with `src/main...` and second with `app/src/main/...`. I have no idea why does this happen – Than Feb 03 '17 at 13:19
  • It was due to inproper working directory in JUnit run configuration as described in @Kirill Vashilo answer – Than Feb 03 '17 at 15:02
0

I've just resolved the same problem with Robolectric (ver: robolectric-2.4-jar-with-dependencies.jar) and returning unknown resources, while loading resouce from different values-* folders e.g.:

<resources>
    <string name="screen_type">10-inch-tablet</string>
</resources>

In my case I wanted to recognize different devices. For this reason, I've created screen.xml in following folders:

values/screen.xml - mobile
values-sw600dp/screen.xml - 7-inch tablet
values-sw720dp/screen.xml - 10-inch tablet

My workspace is as following:

workspace
   \-ExProj
       \-exProj
            \-src
                \-exProj
                    \-AndroidManifest.xml
   \-ExProjTest

My unit test with Robolectric:

@RunWith(RobolectricTestRunner.class)
@Config(manifest = "./../ExProj/exProj/src/exProj/AndroidManifest.xml")
public class UtilityTest {

  @Test
   @Config(qualifiers = "sw720dp")
    public void testIfDeviceIsTablet() throws Exception {
     System.out.println(Robolectric.application.getString(R.string.screen_type));
    }
}

Above test code prints out on the console: 10-inch-tablet...

damax
  • 453
  • 1
  • 5
  • 18
0

I overrode getConfigProperties() by subclassing RobolectricTestRunner. Please follow this link: https://stackoverflow.com/a/29907234/727654

Community
  • 1
  • 1
Nishant Soni
  • 658
  • 1
  • 9
  • 19