Reputation: 3139
In my app,I have a login and a register fragment. I want to test their views ie if the edit texts have hints,and their buttons. I will put here by login fragment which contains two editi texts and one button. There is also a webservice,but I will test it at a later point.
public class LoginFragment extends Fragment {
Button loginButton;
EditText etName,etPass;
String login_name;
String login_pass;
private SessionManager session;
TextView forgotPassBtn;
public LoginFragment() {
// 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_login, container, false);
Toolbar myToolbar = (Toolbar) v.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(myToolbar);
setHasOptionsMenu(true);
etName = (EditText)v.findViewById(R.id.user_name);
etPass = (EditText)v.findViewById(R.id.user_pass);
loginButton = (Button) v.findViewById(R.id.loginButton);
login_name = etName.getText().toString();
login_pass = etName.getText().toString();
forgotPassBtn = (TextView) v.findViewById(R.id.forgotPass);
session = new SessionManager(getActivity());
if (session.isLoggedIn()) {
// User is already logged in. Take him to main activity
Intent intent = new Intent(getActivity(), Welcome.class);
startActivity(intent);
getActivity().finish();
}
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
login_name = etName.getText().toString();
login_pass = etPass.getText().toString();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());
SharedPreferences.Editor editor = settings.edit();
if(login_name.isEmpty() && login_pass.isEmpty()) {
Toast.makeText(getActivity(),"Username η κωδικός είναι κενό",Toast.LENGTH_SHORT).show();
}else {
editor.putString("id", "");
editor.putString("user_name", login_name);
editor.putString("user_pass", login_pass);
editor.commit();
loginUser(login_name, login_pass);
}
}
});
return v;
}
private void loginUser(final String userName,
final String password) {
/*
Tag used to cancel the request
HttpsTrustManager.sssMethod();
*/
String tag_string_req = "req_register";
StringRequest strReq = new StringRequest(Request.Method.POST,
Config.URL_LOGIN, 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")) {
session.setLogin(true);
Toast.makeText(getActivity(), jsonObject.getString("message"), Toast.LENGTH_LONG).show();
Intent intent = new Intent(getActivity(),
Welcome.class);
startActivity(intent);
getActivity().finish();
}
else if (jsonObject.getString("result").equals("fail")) {
Toast.makeText(getActivity(),jsonObject.getString("message"), Toast.LENGTH_LONG).show();
}
}catch(JSONException e){
e.printStackTrace();
}
// Launch login activity
//Toast.makeText(getApplicationContext(), "User successfully registered. Try login now!", Toast.LENGTH_LONG).show();
}
}, 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("user_name", userName);
params.put("user_pass", password);
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
}
Now I am doing some testing with Robolectric.
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class,sdk = 21)
public class LoginFragmentTest {
MainActivity activity;
Button loginButton;
@Before
public void setUp() throws Exception {
activity = Robolectric.setupActivity(MainActivity.class);
loginButton = getButton(activity,R.id.registerBtn);
}
@Test
public void loginFragmentShouldNotBeNull(){
LoginFragment loginFragment = new LoginFragment();
startFragment(loginFragment, AppCompatActivity.class);
assertNotNull(loginFragment);
}
@Test
public void shouldHaveUserNameEntry() throws Exception{
EditText nameEntry = getEditText(activity,R.id.user_name);
assertViewIsVisible(nameEntry);
assertThat(nameEntry.getHint().toString(),equalTo(ResourceLocator.getString(R.string.login_username)));
}
}
The getEditText method is defined in another class.
public class ViewLocator {
public static TextView getTextView(Activity activity, int viewId){
return ((TextView)activity.findViewById(viewId));
}
public static EditText getEditText(Activity activity, int viewId){
return ((EditText)activity.findViewById(viewId));
}
public static Button getButton(Activity activity, int viewId){
return ((Button) activity.findViewById(viewId));
}
}
When I run the LoginFragmentTest I get an error on the shouldHaveUserNameEntry() method
java.lang.NullPointerException
at team.football.ael.LoginFragmentTest.shouldHaveUserNameEntry(LoginFragmentTest.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
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 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Any ideas how to test that edit text view succesfully?
The
assertViewIsVisible(nameEntry);
passes. The error appears in
assertThat(nameEntry.getHint().toString(),equalTo(ResourceLocator.getString(R.string.login_username)));
Thanks,
Theo.
Upvotes: 4
Views: 6080
Reputation: 1104
Here you add your login fragment on an AppCompactActivity initialized by the startFragment method
@Test
public void loginFragmentShouldNotBeNull() {
LoginFragment loginFragment = new LoginFragment();
startFragment(loginFragment, AppCompatActivity.class);
assertNotNull(loginFragment);
}
Then you try to find the user_name field on the mainActivity. You added your fragment on an AppCompatActivity and not on your MainActivity (I suppose you add your fragment dynamically in your MainActivity). So the EditText does not exist
@Test
public void shouldHaveUserNameEntry() throws Exception {
EditText nameEntry = getEditText(activity,R.id.user_name);
assertViewIsVisible(nameEntry);
assertThat(nameEntry.getHint().toString(),equalTo(ResourceLocator.getString(R.string.login_username)));
}
I don't think you need to test your MainActivity. You could use the method startVisibleFragment from SupportFragmentTestUtil which initialize your fragment on an AppCompatActivity
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class,sdk = 21)
public class LoginFragmentTest {
private LoginFragment mLoginFragment = new LoginFragment();
@Before
public void setUp() throws Exception {
SupportFragmentTestUtil.startVisibleFragment(mLoginFragment);
}
@Test
public void shouldHaveUserNameEntry() throws Exception{
EditText nameEntry = mLoginFragment.getActivity().findViewById(R.id.user_name);
assertViewIsVisible(nameEntry);
assertThat(nameEntry.getHint().toString(),equalTo(RuntimeEnvironment.application.getResources().getString(R.string.login_username)));
}
Upvotes: 5