Application Context in Robolectric Tests

8,106 views
Skip to first unread message

Justin

unread,
Apr 30, 2012, 6:19:24 PM4/30/12
to Robolectric
Hey Everybody,

A lot of my Activities are dependent on an Application object, which
contains a lot of session and runtime information about the app I'm
testing.

How do people build an Application object/context and make sure it's
attached to Activities as they're being tested?

In my case there's code like this in some of my Activities:

getMyApplication().getSession().getSignedInAccount()...

But obviously, when I write a test like this:

MyActivity myActivity = new MyActivity();
myActivity.onCreate(null);

...there's no Application context, and it results in a null pointer
Exception.

I'm considering writing a test utility method called
getMyApplication() that stubs everything out, and then using the
stubbed Application to start subsequent Activities.

Anybody have any other advice? How do you deal with these situations?

Thanks!

</Justin>

Rick Kawala

unread,
Apr 30, 2012, 6:33:11 PM4/30/12
to robol...@googlegroups.com
I make sure my test class is annotated with @RunWith(RobolectricTestRunner.class), and then I can reference Robolectric.application in my test.

Best,
Rick

Justin

unread,
Apr 30, 2012, 6:35:38 PM4/30/12
to robol...@googlegroups.com
Right, I'm doing that too. In my case I created a custom test runner that inherits from RobolectricTestRunner. 

But... how do people deal with Application state? Almost all of my app's user state information is tied to the Application context.

How do those things get populated on the Application context when testing with Robolectric?

So far, I've been able to test simple things, but not anything that depends on this Application state (most of which is instantiated in Application onCreate()). 

Thanks!

</Justin>

Jan Berkel

unread,
May 1, 2012, 7:53:54 AM5/1/12
to robol...@googlegroups.com
So far, I've been able to test simple things, but not anything that depends on this Application state (most of which is instantiated in Application onCreate()). 


you can also create a subclass of your Application and tell robolectric to use it:

public class TestApplication extends MyApplication {
  //
}

public class DefaultTestRunner extends RobolectricTestRunner {
    public static TestApplication application;

    public DefaultTestRunner(Class testClass) throws InitializationError {
        super(testClass, new RobolectricConfig(new File(".")) {
            @Override public String getApplicationName() {
                return TestApplication.class.getSimpleName();
            }
        });
    }

    @Override
    public void beforeTest(Method method) {
        application = (TestApplication) Robolectric.application;
}

your testapplication can then be used to fix certain behaviour / mock state etc.
 
In my testcode i use a reference to DefaultTestRunner.application to avoid having to cast every time.
if your Application object has any static state make sure to clear it out in the testrunners 'resetStaticState' method.


   jan


Justin

unread,
May 1, 2012, 12:48:31 PM5/1/12
to robol...@googlegroups.com
Thanks for the info, Jan!

One problem I see with this: How can I cast an object of type MyMainApplication to MyTestApplication, if MyTestApplication is a subclass of MyMainApplication?

I've:
* Built an empty class called MyTestApplication that inherits from my main app application class
* Implemented the code in my TestRunner to add a reference to this application

But, I'm getting a ClassCastException (which makes sense): 
MainApplication cannot be cast to com.blah.tests.application.MainTestApplication

Are you using an interface or something to resolve this cast Exception?

Michael Portuesi

unread,
May 1, 2012, 1:00:03 PM5/1/12
to robol...@googlegroups.com
Justin,

The approach that Jan describes is basically the same as we use for our project at work.

We're successfully creating an instance of MyTestApplication and casting it in the test case

I think one difference is that we have a custom test runner that overrides RoboelectricTestRunner's createApplication() method.  Here's a slightly altered example of what we're using:

@Override
protected Application createApplication() {
    TestApp testApplication = new TestApp();
    ShadowContextWrapper shadowApp = Robolectric.shadowOf( testApplication );
    shadowApp.setPackageName( "com.mycompany.myapp" );
    shadowApp.setPackageManager(new RobolectricPackageManager(testApplication, robolectricConfig));
    testApplication.onCreate();
    return testApplication;    

}

At that point, Robolectric.application is an instance of the TestApp:

private TestApp mApplication;

public class MyActivityTest {

    private TestApp mApplication;

    @Before
    public void setUp() throws Exception { 
        mApplication = (TestApp) Robolectric.application;
    }


Hope this helps,
Michael Portuesi

Justin

unread,
May 2, 2012, 7:41:30 PM5/2/12
to robol...@googlegroups.com
You dudes are gentleman and scholars.  

Thanks a lot for the help! 

I've got another small issue that belongs in another thread. I'll fight with it a bit more before posting. :)

minesh patel

unread,
Sep 27, 2014, 10:29:18 PM9/27/14
to robol...@googlegroups.com, jmscon...@gmail.com
Hi Guys,
I was following this solution. One thing I did not understand was what is TestApp here? Please explain.


On Monday, April 30, 2012 3:19:24 PM UTC-7, Justin wrote:
Reply all
Reply to author
Forward
0 new messages