I have been reading a lot of links from here, github and robolectric blog but couldn't find a working solution yet (already using Robolectric 2.0 alpha 2).
UPDATE: The problem also happens even if we replace SherlockFragment
for android.support.v4.app.Fragment
.
I was able to test a SherlockFragmentActivity after following this tip, but when I add this fragment, that is a SherlockFragment, to my activity xml:
<fragment
android:name="com.marcelopazzo.fragmentapplication.ExampleFragment"
android:id="@+id/example_fragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
The SherlockFragment class:
public class ExampleFragment extends SherlockFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
And this is the layout that is being inflated by the fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/hello_again"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_again" />
</LinearLayout>
I get the following error:
java.lang.NullPointerException
at org.robolectric.shadows.ShadowViewGroup.addView(ShadowViewGroup.java:69)
at android.view.ViewGroup.addView(ViewGroup.java)
at org.robolectric.res.builder.LayoutBuilder.constructFragment(LayoutBuilder.java:150)
at org.robolectric.res.builder.LayoutBuilder.create(LayoutBuilder.java:104)
at org.robolectric.res.builder.LayoutBuilder.doInflate(LayoutBuilder.java:42)
at org.robolectric.res.builder.LayoutBuilder.doInflate(LayoutBuilder.java:45)
at org.robolectric.res.builder.LayoutBuilder.inflateView(LayoutBuilder.java:62)
at org.robolectric.shadows.ShadowLayoutInflater.inflate(ShadowLayoutInflater.java:50)
at org.robolectric.shadows.ShadowLayoutInflater.inflate(ShadowLayoutInflater.java:55)
at android.view.LayoutInflater.inflate(LayoutInflater.java)
at com.squareup.test.ActionBarSherlockRobolectric.setContentView(ActionBarSherlockRobolectric.java:38)
at com.actionbarsherlock.app.SherlockFragmentActivity.setContentView(SherlockFragmentActivity.java:262)
at com.marcelopazzo.fragmentapplication.MainActivity.onCreate(MainActivity.java:13)
at com.marcelopazzo.fragmentapplication.MainActivityTest.setUp(MainActivityTest.java:33)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:110)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:234)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:133)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:114)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:188)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:166)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:86)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:101)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:74)
This is the test class that I am using:
@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {
private MainActivity activity;
private TextView textView;
public static final String GREETINGS = "Hello world!";
@Before
public void setUp() {
ActionBarSherlock.registerImplementation(ActionBarSherlockRobolectric.class);
ActionBarSherlock.unregisterImplementation(ActionBarSherlockNative.class);
ActionBarSherlock.unregisterImplementation(ActionBarSherlockCompat.class);
activity = new MainActivity();
activity.onCreate(null);
textView = (TextView) activity.findViewById(R.id.hello);
}
@Test
public void shouldGreet() {
assertEquals(GREETINGS, textView.getText());
}
}
The application is working fine on the device.
What am I missing here?
ps: The full source code is available on github
Edit: Also tested with the code from square/master (2.0 alpha 3 square 5) branch and got the same problem.
Checking the LayoutBuilder.constructFragment
, I think the problem is that activity.getSupportFragmentManager().beginTransaction().add(fragment, tag).commit()
is not working with SherlockFragment, so fragment.getView()
is returning null.
I'm not sure if I can do anything on my side to fix this... I'm already checking if I can fix it on robolectric's side, please let me know if anyone have any tip on this.
If yes then, you must try Robolectric, it is a unit testing framework that allows Android applications to be tested on the JVM without an emulator or device. These are the main features of it:
You can also use the findViewById () to search in a view. Robolectric is not an integration test framework, i.e., you cannot not test the interaction of Android components with it. Robolectric does not require additional mocking frameworks, of course it is still possible to use frameworks like Mockito if desired.
These are the main features of it: It provides a way to run our tests inside Android Studio, without launching app on Device or Emulator. Shadow Classes, rewritten android core libraries by Robolectric, are the real magic of Robolectric. It is a replica of Android class with some exposed useful functions.
Every time a method is invoked on the Android class, Robolectric first invokes the shadow class' corresponding method (if there is one). This gives the shadow classes a chance to maintain and expose extra state that wouldn't be available from just the Android classes. Let's assume our MainActivity has a Button that launches a SecondActivity.
You might try using Robolectric 2.0's new ActivityController, which fixes some scheduling/order-of-operations issues that often crop up.
MainActivity activity = Robolectric.buildActivity(MainActivity.class)
.create().get();
It arranges for the main looper to be temporarily paused during the call to onCreate().
Calling
Robolectric.buildActivity(YourActivityClass.class).attach().create().start().resume().get();
will call your Fragment.onCreateView method
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With