Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Fragments with Robolectric 3.0

I have two fragments attached to an activity.

public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    LoginFragment loginFragment = new LoginFragment();
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction =    
    fragmentManager.beginTransaction();
    fragmentTransaction.add(android.R.id.content,loginFragment);
    fragmentTransaction.commit();
  }

   public void userReg(View view){
    RegisterFragment regFragment = new RegisterFragment();
    FragmentManager fragmentManager1 = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction1 = 
    fragmentManager1.beginTransaction();
    fragmentTransaction1.addToBackStack("added");
    fragmentTransaction1.replace(android.R.id.content,regFragment);
    fragmentTransaction1.commit();
   }

}

The registration fragment attached via a button. Now I want to test both of them in robolectric 3.0.

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class,sdk = 21)

public class MainActivityTest {
MainActivity activity;
@Before
public void setUp(){
      activity= Robolectric.setupActivity(MainActivity.class);
}

@Test
public void shouldNotBeNull(){
    assertNotNull(activity);
    LoginFragment loginFragment = new LoginFragment();
    startFragment(loginFragment);
    assertNotNull(loginFragment);
   }

 @Test
public void loginFragmentShouldNotBeNull(){
    RegisterFragment registerFragment = new RegisterFragment();
    startFragment(registerFragment);
    assertNotNull(registerFragment);

   }
   @Test
   public void registerFragmentShouldNotBeNull(){
    RegisterFragment registerFragment = new RegisterFragment();
    startFragment(registerFragment);
    assertNotNull(registerFragment);

   }
 }

These line complain

        startFragment(loginFragment);
        startFragment(registerFragment);

saying that startFragment(android.app.Fragment) can not be applied in LoginFragment and Register fragment respectively.

For both fragments I import

import android.support.v4.app.Fragment;

so this is causing the problem. I could have fix this issue,by using fixed fragments,but how about using dynamic ones?

Any ideas?

Thanks.

EDIT

The error described above is fixed. I just added

import static org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment;

However,when I run the test I get another exception.

java.lang.ClassCastException: org.robolectric.shadows.support.v4.SupportFragmentTestUtil$FragmentUtilActivity cannot be cast to android.support.v7.app.AppCompatActivity

at fragments.LoginFragment.onCreateView(LoginFragment.java:64)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2074)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1286)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:758)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1671)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:532)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at org.robolectric.shadows.ShadowMessageQueue.dispatchMessage(ShadowMessageQueue.java:144)
at org.robolectric.shadows.ShadowMessageQueue.access$100(ShadowMessageQueue.java:30)
at org.robolectric.shadows.ShadowMessageQueue$1.run(ShadowMessageQueue.java:105)
at org.robolectric.util.Scheduler.runOrQueueRunnable(Scheduler.java:293)
at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:143)
at org.robolectric.shadows.ShadowMessageQueue.enqueueMessage(ShadowMessageQueue.java:126)
at android.os.MessageQueue.enqueueMessage(MessageQueue.java)
at android.os.Handler.enqueueMessage(Handler.java:631)
at android.os.Handler.sendMessageAtTime(Handler.java:600)
at android.os.Handler.sendMessageDelayed(Handler.java:570)
at android.os.Handler.post(Handler.java:326)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1557)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:654)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:621)
at org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment(SupportFragmentTestUtil.java:17)
at team.football.ael.MainActivityTest.loginFragmentShouldNotBeNull(MainActivityTest.java:34)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:527)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:265)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:191)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:56)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:157)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)



java.lang.ClassCastException: 

org.robolectric.shadows.support.v4.
SupportFragmentTestUtil$FragmentUtilActivity 
cannot be cast to android.support.v7.app.AppCompatActivity

at fragments.RegisterFragment.onCreateView(RegisterFragment.java:54)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2074)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1286)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:758)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1671)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:532)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at org.robolectric.shadows.ShadowMessageQueue.dispatchMessage(ShadowMessageQueue.java:144)
at org.robolectric.shadows.ShadowMessageQueue.access$100(ShadowMessageQueue.java:30)
at org.robolectric.shadows.ShadowMessageQueue$1.run(ShadowMessageQueue.java:105)
at org.robolectric.util.Scheduler.runOrQueueRunnable(Scheduler.java:293)
at org.robolectric.util.Scheduler.postDelayed(Scheduler.java:143)
at org.robolectric.shadows.ShadowMessageQueue.enqueueMessage(ShadowMessageQueue.java:126)
at android.os.MessageQueue.enqueueMessage(MessageQueue.java)
at android.os.Handler.enqueueMessage(Handler.java:631)
at android.os.Handler.sendMessageAtTime(Handler.java:600)
at android.os.Handler.sendMessageDelayed(Handler.java:570)
at android.os.Handler.post(Handler.java:326)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1557)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:654)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:621)
at org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment(SupportFragmentTestUtil.java:17)
at team.football.ael.MainActivityTest.registerFragmentShouldNotBeNull(MainActivityTest.java:41)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:527)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:265)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:191)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:56)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:157)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

EDIT 2

This is my RegisterFragment

public class RegisterFragment extends Fragment {
private SessionManager session;
EditText etEmail, etUsername, etPassword,etConfirmPassword;
String email, userName, userPass,confirmPassword;
Button registerButton;

public RegisterFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_register, container, false);
    Toolbar myToolbar = (Toolbar) v.findViewById(R.id.toolbar);
    ((AppCompatActivity)getActivity()).setSupportActionBar(myToolbar);
    setHasOptionsMenu(true);


    etEmail = (EditText)v.findViewById(R.id.name);
    etUsername = (EditText)v.findViewById(R.id.user_name);
    etPassword = (EditText)v.findViewById(R.id.user_pass);
    etConfirmPassword = (EditText)v.findViewById(R.id.confirm_pass);
    registerButton = (Button)v.findViewById(R.id.registerBtn);
    // Session manager
    // Session manager
    session = new SessionManager(getActivity());

    if (session.isLoggedIn()) {
        // User ites already logged in. Take him to main activity
        Intent intent = new Intent(getActivity(), Welcome.class);
        startActivity(intent);

    }
    registerButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            email = etEmail.getText().toString();
            userName = etUsername.getText().toString();
            userPass = etPassword.getText().toString();
            confirmPassword = etConfirmPassword.getText().toString();

            if(userPass.equals(confirmPassword)){

                registerUser(email, userName, userPass, confirmPassword);

            }else{

                Toast.makeText(getActivity(),"Passwords don't match",Toast.LENGTH_SHORT).show();
            }
        }
    });

    return v;
}
private void registerUser(final String email, final String userName,
                          final String password,final String confirmPassword) {
    // Tag used to cancel the request

    //HttpsTrustManager.sssMethod();
    String tag_string_req = "req_register";


    StringRequest strReq = new StringRequest(Request.Method.POST,
            Config.URL_REGISTER, new Response.Listener<String>() {

        @Override
        public void onResponse(String response) {
            Log.d("Response", "Register Response: " + response.toString());

            try {
                JSONObject jsonObject = new JSONObject(response);
                if (jsonObject.getString("result").equals("success")) {



                    Toast.makeText(getActivity(),jsonObject.getString("message"), Toast.LENGTH_LONG).show();

                    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putString("id","");
                    editor.putString("email", email);
                    editor.putString("user_name", userName);
                    editor.putString("user_pass", password);
                    editor.putString("confirm_pass", confirmPassword);


                }

                else if (jsonObject.getString("result").equals("fail")) {

                    Toast.makeText(getActivity(),jsonObject.getString("message"), Toast.LENGTH_LONG).show();

                }

            }catch(JSONException e){
                e.printStackTrace();
            }


        }


    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e("Error", "Registration Error: " + error.getMessage());
            Toast.makeText(getActivity(),
                    error.getMessage(), Toast.LENGTH_LONG).show();

        }
    }) {

        @Override
        protected Map<String, String> getParams() {
            // Posting params to register url
            Map<String, String> params = new HashMap<String, String>();
            params.put("id","");
            params.put("email", email);
            params.put("user_name", userName);
            params.put("user_pass", password);
            params.put("confirm_pass", confirmPassword);
            return params;
        }

    };

    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
   }

}

like image 731
Theo Avatar asked Jul 06 '16 08:07

Theo


People also ask

Is Robolectric deprecated?

Robolectric is intended to be fully compatible with Android's official testing libraries since version 4.0. As such we encourage you to try these new APIs and provide feedback. At some point the Robolectric equivalents will be deprecated and removed.

What is AndroidX test?

AndroidX Test is a collection of Jetpack libraries that lets you run tests against Android apps. It also provides a series of tools to help you write these tests. For example, AndroidX Test provides JUnit4 rules to start activities and interact with them in JUnit4 tests.


2 Answers

Your fragments inherit from "Support fragments" (the ones from android support library), but your startFragment() function expects regular fragments. You can use SupportFragmentTestUtil.startFragment(fragment, activityClass)

Support library allows to use fragments on API levels where no fragments were supported yet. If your application is expected to run on API 11 and above (Android 3) - you can derive your fragments from android.app.Fragment directly

like image 182
Denis Itskovich Avatar answered Oct 18 '22 20:10

Denis Itskovich


Bit late but for others, this works well for androidx.fragment.app.Fragment and robolectric 4:

@RunWith(RobolectricTestRunner::class)
class YourFragmentTest {

    lateinit var yourFragment: YourFragment

    @Before
    fun setUp() {
        val activity = Robolectric.buildActivity(FragmentActivity::class.java)
            .create()
            .start()
            .resume()
            .get()

        yourFragment = YourFragment()
        activity.supportFragmentManager.beginTransaction().apply {
            add(yourFragment, "YourFragment")
            commit()
        }
    }

    @Test
    fun testYourMethod() {
        assertTrue(yourFragment.YourMethod())
        ....
    }
}
like image 42
Sumit Sharma Avatar answered Oct 18 '22 21:10

Sumit Sharma