Using Gradle generated Android resources with Robolectric
June 26, 2015In a previous blog post, I talked about how Gradle allows us to add string resources that can be changed depending on your build configuration, like so:
android { buildTypes { debug { resValue "string", "google_maps_android_api_key", "abcdefghijklm123" } release { resValue "string", "google_maps_android_api_key", "nopqrstuvwxyz456" } } }
This generates a string resource that we can then use in our code:
String mapsKey = getString(R.string.google_maps_android_api_key);
However, if you use the Robolectric testing framework (version 2.4) and this line is executed during a test, then you will get the following error in your LogCat:
android.content.res.Resources$NotFoundException: String resource ID #0x7f0c004e
Since this string resource is only generated during a Gradle build and not during Robolectric test execution, Robolectric is not able to find this string resource and this exception is thrown.
The solution
If we attempt to put a dummy string in our strings.xml file…
<string name="google_maps_android_api_key">dummy maps key</string>
…so that this exception doesn’t happen, Robolectric tests will run just fine, but when you build your project it will complain about duplicate resources, as Gradle is trying to generate a resource of the same name.
The solution is to create a shadow resource for this generated string. Create the following class in your test package:
import android.content.res.Resources; import org.robolectric.annotation.Implements; import org.robolectric.shadows.ShadowResources; /** * This class is used to generate Android resources that are otherwise * not present during Robolectric tests, such as string resources generated * by Gradle with resValue. */ @Implements(Resources.class) public class CustomShadowResources extends ShadowResources { @Override public CharSequence getText(int id) throws Resources.NotFoundException { if (id == R.string.google_maps_android_api_key) return "dummy maps key"; return super.getText(id); } }
In your test class that is throwing the exception, add a “shadows” annotation parameter to your “Config” annotation that points to your new shadow class:
@Config( shadows = CustomShadowResources.class, ... ) @RunWith(RobolectricTestRunner.class) public class SomeActivityTest { ... }
How it works
The shadow class defines what to do when Robolectric comes across certain types of resources. In this case, when your code tries to access the generated string resource…
String mapsKey = getString(R.string.google_maps_android_api_key);
…Robolectric will use the shadow class’s overridden method to return a dummy string when testing execution comes across use of this string resource, and the Resources$NotFoundException will no longer be thrown.
Looking for more like this?
Sign up for our monthly newsletter to receive helpful articles, case studies, and stories from our team.
![How to Prepare for our Associate Software Developer Position](https://gratis-creeper.transforms.svdcdn.com/staging/blog/banner.jpg?w=696&h=320&q=75&auto=format&fit=crop&dm=1708017432&s=dc820db96cf01aa4add473b4b6588bdd)
How to Prepare for our Associate Software Developer Position
June 30, 2023Tips for applying to MichiganLab's Associate Software Developer program
Read more![How to approach legacy API development](https://gratis-creeper.transforms.svdcdn.com/staging/blog/legacy-api-thumbnail.jpg?w=1080&h=1080&auto=compress%2Cformat&fit=crop&dm=1712166544&s=336e5f9a61c0c6ec1d3ff90cc58ea1c9)
How to approach legacy API development
April 3, 2024Legacy APIs are complex, often incompatible, and challenging to maintain. MichiganLabs’ digital product consultants and developers share lessons learned for approaching legacy API development.
Read more![What to know about the cost of custom app development](https://gratis-creeper.transforms.svdcdn.com/staging/blog/Custom-app_web-thumbnail-1080x1080-px.png?w=1080&h=1080&auto=compress%2Cformat&fit=crop&dm=1708017468&s=ddd49f5cb9b41e947fcc9157bc8a7d73)
What to know about the cost of custom app development
January 10, 2024We hear a lot of ideas for apps at MichiganLabs. People from large enterprises and small startups, located all over the world, call us to explore their mobile and web-based application ideas, and one of the first questions they ask is: How much is this app going to cost?
Read more