Testing custom Views with Robolectric
I test views in the same test class with the Activity that uses them. In this case I tell Robolectric to give an instance of that Activity and from that I get an instance of the inflated view:
@Before
public void setup(){
activity = Robolectric.buildActivity(MyActivity.class).create().get();
View view = LayoutInflater.from(activity).inflate(R.layout.myView, null);
}
@Test
public void allElementsInViewProduct(){
assertNotNull(view.findViewById(R.id.view1));
assertNotNull(view.findViewById(R.id.view2));
assertNotNull(view.findViewById(R.id.view3));
}
LE: I use Robolectric 3.0 so I am not sure if this applies to you.
Problem:
This issue happens, because gradle merges project dependencies (ex: compile project(':lib-custom')
) and external dependencies (ex: compile 'lib.package:name:1.1.0'
) in different way. After dependencies were merged app has R.java
file with all resources fields (colors, ids, drawables, ...). But generated R.java
file looks different after merging submodules and external dependencies.
This problem exists only with projects, which have custom views in submodules. In case of external dependencies there is another issues, which can be easily fixed. Read about dependencies types here.
For project dependencies result R.java
file contains all resource identifiers, but identifiers from submodule doesn't equals to their original integer identifiers:
com.lib.custom.R.color.primary != com.main.project.R.color.primary
For external dependencies merged R.java
file just a merge result of R.java files from all external dependencies
com.lib.custom.R.color.primary == com.main.project.R.color.primary
Solution:
I've found two possible solutions:
- Convert your dependencies from submodule to external where possible. For example for viepager indicator has an item in maven.org repository - fr.avianey.com.viewpagerindicator:library. But this is still not enough - you need to add related item to project.properties file to your main sourceSet. More info here
Example:
// add this dependency to your gradle file instead of project dependency
compile 'fr.avianey.com.viewpagerindicator:library:2.4.1@aar'
// add library dependencies for robolectric (now robolectric knows
// about additional libraries to load resources)
android.library.reference.1=../../../app/build/intermediates/exploded-aar/fr.avianey.com.viewpagerindicator/library/2.4.1
You can check diff for this solution here
- Move all your custom views under your main app. It is not good approach to move Custom views to app only because of unit testing, but this will also fix issue with
Error inflating class
.
I prefer first solution but it is not possible sometimes change project dependency to external.
I am also going to report about this issue to Robolectric team.
P.S. I have project on github related to this issue.