I\'m trying to run unit tests with Robolectric 2.1.1 and I cannot get it to inflate custom layouts (e.g. ViewPagerIndicator classes). Suppose this is my layout:
<
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
I've found two possible solutions:
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
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.
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.
mTestRoboActivityView = LayoutInflater.from(new Activity()).inflate(R.layout.test, null);
In this line of code you used 'new Activity()' means instance of new Activity, that not for your current Activity. You can resolve this issue by passing instance on current Activity. Use like this-
public class TestRoboActivityTest {
private View mTestRoboActivityView;
private Context mContext;
public TestRoboActivityTest(Context mContext){
this.mContext=mContext;
}
@Before
public void setUp() throws Exception {
mTestRoboActivityView = (LayoutInflater.from(mContext)).inflate(R.layout.test, null);
}
@After
public void tearDown() throws Exception {
mTestRoboActivityView = null;
}
@Test
public void testSanity() throws Exception {
Assert.assertNotNull(mTestRoboActivityView);
}}
I am not sure that above code working fine but use for reference, instance of current Activity. Refer it may be help you.
You cannot inflate views in Roboelectric since it does not use the complete android framework but instead mocks out all the Android API's.
You should not use roboelectric to test actual view display behavior. It is to be used for unit tests and just to test your business logic and not view drawing/display etc. To achieve that You can programmatically create view objects and mock out certain parts which need the android system (Use something like Mockito or Powermock). eg of simple view testing in roboelectic:
MyCustomView view = new MyCustomView();
assertNotNull(view.setSomeNo(2);
assertTrue(2, view.getSomeNo());
Also if you want to test rendering of how your view looks or renders etc, you should use functional testing frameworks such as Espresso or Robotium which run on an actual device.