Search code examples
androidandroid-espressoandroid-annotations

Can setContentView be replaced by android-annotations when espresso is used?


I have espresso test which verifies that text is displayed:

public class InformationActivityTests {
    @Rule
    public ActivityTestRule<InformationActivity_> mInformationActivityTestRule =
            new ActivityTestRule<InformationActivity_>(InformationActivity_.class) {
                @Override
                protected Intent getActivityIntent() {
                    Intent i = new Intent(getTargetContext(), InformationActivity_.class);
                    i.putExtra("INFORMATION", "Espresso");
                    return i;
                }
            };

    @Test
    public void textIsDisplayed() {
        onView(withText("Espresso")).check(matches(isDisplayed()));
    }
}

This test passes when Activity has following code:

@EActivity
public class InformationActivity extends AppCompatActivity {
    @ViewById(R.id.information_view)
    TextView informationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_information);

        Intent intent = getIntent();
        String information = intent.getStringExtra("INFORMATION");
        informationView.setText(information);
    }
}

but fails when I "move" setContentView to @EActivity annotation:

@EActivity(R.layout.activity_information)
public class InformationActivity extends AppCompatActivity {
    @ViewById(R.id.information_view)
    TextView informationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        String information = intent.getStringExtra("INFORMATION");
        informationView.setText(information);
    }
}

Error is:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.edu/com.edu.InformationActivity_}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference

Am I doing something wrong or is it an issue with espresso / android-annotations?


Solution

  • I've checked code generated by android-annotations when using @EActivity(R.layout.activity_information) and this is how onCreate looks like in generated class (InformationActivity_):

    public void onCreate(Bundle savedInstanceState) {
        OnViewChangedNotifier previousNotifier = OnViewChangedNotifier.replaceNotifier(onViewChangedNotifier_);
        init_(savedInstanceState);
        super.onCreate(savedInstanceState);
        OnViewChangedNotifier.replaceNotifier(previousNotifier);
        setContentView(R.layout.activity_information);
    }
    

    the problem is that it first calls super.onCreate (so onCreate from InformationActivity) where I handle intent and TextView and then it calls setContentView and this can't work like that.

    The solution for this is what Be_Negative suggested, so using @AfterViews annotation. It also simplifies code a bit (I could remove onCreate method):

    @EActivity(R.layout.activity_information)
    public class InformationActivity extends AppCompatActivity {
        @ViewById(R.id.information_view)
        TextView informationView;
    
        @AfterViews
        void handleIntent() {
            Intent intent = getIntent();
            String information = intent.getStringExtra("INFORMATION");
            informationView.setText(information);
        }    
    }