IllegalStateException in Roboelectric with SupportFragmentTestUtil.startVisibleFragment(myFragment) - java

I'm setting up this class for testing my fragment:
#RunWith(RobolectricTestRunner.class)
public class MyFragmentTest {
MyFragment myFragment;
#Before
public void setUp(){
myFragment = (MyFragment)FmyFragment.instantiate(ApplicationProvider.getApplicationContext(), MyFragment.class.getName());
SupportFragmentTestUtil.startVisibleFragment(myFragment);
}
}
But the line
SupportFragmentTestUtil.startVisibleFragment(myFragment);
is throwing the following exception:
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
Did I miss something in my setup? I've tried many things and this is the closest I've been to starting my fragment with roboelectric.
If you need more info, feel free to ask.

The problem was with a Glide Bug when using roboelectric.

Related

Android view model class has no zero argument constructor,Instantiation Exception in fragment [duplicate]

This question already has an answer here:
Cannot create instance of class ViewModel while using MVVM
(1 answer)
Closed 2 years ago.
i have a view model class and i need to instantiate it in a fragment.
But I am getting :
java.lang.RuntimeException: Cannot create an instance of class com.example.project.favourites.FavViewModel
and
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.project.favourites.FavViewModel> has no zero argument constructor
This is the line causing crash:
favViewModel= new ViewModelProvider(this).get(FavViewModel.class);
(This line is within onViewCreated in fragment)
pls help!!!!!
Below is FavViewModel Class
public class FavViewModel extends AndroidViewModel {
private FavRepository repository;
private LiveData<List<FavItem>> allFav;
public FavViewModel(#NonNull Application application) {
super(application);
repository=new FavRepository(application);
allFav=repository.getAllFav();
}
public void insert(FavItem favItem){
repository.insert(favItem);
}
public void delete(FavItem favItem){
repository.delete(favItem);
}
public void deleteAll(){
repository.deleteAll();
}
public LiveData<List<FavItem>> getAllFav(){
return allFav;
}
}
You can annotate your model class with below annotation
#NoArgsConstructor
You will get more idea about lombok , NoArgsConstructor and many more annotations using this linklombok
Try using this...
Initialise ViewModel like this. You need to also pass ViewModelFactory with ViewModelProvider constructor.
favViewModel = new ViewModelProvider(this,
new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(FavViewModel.class);
Hope this helps. Feel free to ask for clarifications...

NoClassDefFoundError while running Roboelectric Unit Test

I am trying to run a Roboelectric Unit test to test if the intended activity is getting started or not, but as I'm getting the following error :
java.lang.NoClassDefFoundError: Could not initialize class
android.os.AsyncTask
I am looking for the solution but no luck so far, Has anyone faced this issue before.
Find below my Test class
#RunWith(RobolectricTestRunner.class)
#Config(constants = BuildConfig.class, manifest = "AndroidManifest.xml", minSdk = 21, maxSdk = 21, application = MyApplication.class)
#PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
public class PushManagerTest {
#Test
public void shouldLaunchNewActivity() throws Exception {
Activity testActivity = Robolectric.setupActivity(TestActivity.class);
Intent expectedIntent = new Intent(testActivity, NewActivity.class);
Intent actualIntent = ShadowApplication.getInstance().getNextStartedActivity();
assertEquals(expectedIntent.getComponent(), actualIntent.getComponent());
}
}
I finally fixed it, dont know if it is the correct way or nor but the tests are working as expected
I had to add the following lines in the onCreate of my Application class
try{
Class.forName("android.os.AsyncTask");
}catch(Throwable ignore) {
// ignored
}
Hope it helps someone

Unable to find Textview in testing

I am unable to find Textview by id in test. What I do wrong?
private MyActivity myActivity;
#Before
public void setUp() throws Exception {
myActivity= Mockito.mock(MyActivity .class);
}
Test:
#Test
public void testFindView() throws Exception {
System.out.println(myActivity); // This is not null
this.myActivity.setContentView(R.layout.container);
TextView viewText = (TextView) this.myActivity.findViewById(R.id.container_text);
System.out.println(viewText ); // This is null
}
Calling Mockito.mock() doesn't create a real instance, but only an artificial one. It's main purpose is to keep unit tests away from any external dependencies and track interactions with an object.
So when you call this.myActivity.setContentView(R.layout.container); nothing really happens, because mocked myActivity doesn't have the insides of a regular MyActivity - you're only calling a stub method that you have not ordered to do anything.
So you need to create a real instance of MyActivity if you want to test how it works. You can also play with Spy objects if you still want to track interactions (you can check them out here)

How to spy on Activity when using Robolectric

I am new on Android and I am playing around with Robolectric for my unit tests.
I am facing the following problem.
I have an activity I want to test.
MainActivity.java
public class MainActivity extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
private NavigationDrawerFragment mNavigationDrawerFragment;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
}
#Override
public void onNavigationDrawerItemSelected (int position) {
...
}
}
This is the test class:
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class)
public class MainActivityTests {
private ActivityController<MainActivity> controller;
private MainActivity activity;
private MainActivity spy;
#Test
public void onCreate_shouldStartNavigationDrawerFragment () {
controller = Robolectric.buildActivity(MainActivity.class);
activity = controller.get();
assertThat(activity).isNotNull();
spy = spy(activity);
spy.onCreate(null);
verify(spy).onCreate(null);
}
}
But I am getting the following exception:
java.lang.IllegalStateException: System services not available to Activities before onCreate() at line spy.onCreate(null).
I have been googling for hours and I have tried several workarounds (blindly) without any success. May please anyone guide me?
Here's what did the trick for me. I use attach() before getting an activity to spy on. Tested with Robolectric 3.0
private MainActivity spyActivity;
#Before
public void setUp(){
MainActivity activity = Robolectric.buildActivity(MainActivity.class).attach().get();
spyActivity = spy(activity);
spyActivity.onCreate(null);
}
You should be driving the activity lifecycle through Robolectric.
See: http://robolectric.org/activity-lifecycle/
So for your case you could do:
controller = Robolectric.buildActivity(MainActivity.class);
activity = controller.get();
assertThat(activity).isNotNull();
spy = spy(activity);
controller.create();
Note: it usually doesn't make sense to spy on the activity lifecycle when testing with Robolectric, since you're the one driving it, so you're only testing that your own method calls executed.
If interested in using exactly the same controller, and work with a spy of the activity, you could modify the inner class of the controller via Reflection, check this method:
public static <T extends Activity> T getSpy(ActivityController<T> activityController) {
T spy = spy(activityController.get());
ReflectionHelpers.setField(activityController, "component", spy);
return spy;
}
The ReflectionHelper is available in Robolectric (tested on Robolectric 4.2). Then it is initialized like this:
controller = Robolectric.buildActivity(MainActivity.class);
activity = getSpy(controller.get());
Hope this helps.
It means that you have to first call the onCreate() method. It has to be the very first called method.

Cannot resolve symbol 'getActivity'

I'm trying to implement a fragment, and am using the Android example as a guide.
In the onActivityCreated() method of the TitlesFragment class, there is this line:
View detailsFrame = getActivity().findViewById(R.id.details);
When I try to include a similar line in my code, I get the error that the 'getActivity' symbol can't be resolved.
I've tried importing everything that their example imports, but it doesn't seem to make any difference. Nor can I find any documentation anywhere that helps me know how to make this accessible.
So, what's the secret on being able to use getActivity?
make sure your class extends Fragment or ListFragment, as shown in the example
public static class TitlesFragment extends ListFragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
View detailsFrame = getActivity().findViewById(R.id.details);
...
}
}

Categories