How to make fun of a method before creating activity?

I have an Activity

public class MyActivity extends ActionBarActivity { public int i; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); i = getSomeInt(); } protected int getSomeInt() { return 1; // here can be an api-request } } 

and I want to test it with robolectric 3.0 and mockito .

But I need to make fun of getSomeInt() methiod.

 @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class) public class MyActivityTest { private MyActivity mActivity; @Before public void setUp() { mActivity = spy(Robolectric.buildActivity(MyActivity.class).create().get()); doReturn(2).when(mActivity).getSomeInt(); //but it is already after onCreate! } @Test public void testGetInt() { assertEquals(2, mActivity.i); //error } } 

Is it possible to use an already mocked method by creating activity?

EDIT

I tried

 @Before public void setUp() { ActivityController<MyActivity> co = Robolectric.buildActivity(MyActivity.class); mActivity = spy(co.get()); doReturn(2).when(mActivity).getSomeInt(); co.create(); } 

but it seems to me that onCreate not called by mActivity

assertEquals(2, mActivity.i); // gives the result:

 java.lang.AssertionError: Expected :2 Actual :0 

thanks Eugen for attention, it does not work, because create calls a controller that works with activity that is not checked

+6
source share
2 answers

Mockito only mocks the object. But it cannot change the link to the ActivityController activity.

Therefore, I am trying to isolate a function and pass on its activity before creating it.

Four steps:

  • Isolate functions as a member of a new class

     public class SomeInt{ public int get() { return 1; // here can be an api-request } } 
  • Use functions with an object in MyActivity

     public class MyActivity extends ActionBarActivity { SomeInt someInt; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); i = someInt.get(); } } 
    1. Create an API to set someInt object in test

      • use ShadowActivity - I recommended this by separating code and test

         @Implements(MyActivity.class) public class ShadowMyActivity extends ShadowActivity { @RealObject private MyActivity myActivity; @Implementation public void setForMockito(SomeInt someint) { myActivity.someint = someint; } } 
      • or leave a public object

        public SomeInt someInt;

      • or make a public setter for an object in MyActivity

    2. Layout in the test

      • If using ShadowActivity

         @Config(constants = BuildConfig.class shadows = ShadowMyActivity.class) Class TestMyActivity { @Before public void setUp() { SomeInt someIntMock = mock(SomeInt.class); ActivityController<MyActivity> co = Robolectric.buildActivity(MyActivity.class); mActivity.setForMockito(someIntMock); doReturn(2).when(someIntMock).get(); co.create(); // verify here or in tearDown } ... } 
+1
source

I do not think that's possible. I tried to create an Activity in the test, spy it, and then create a controller with this spy, and I could not get it to work, so I can’t imagine how you could do it.

Now that it’s said, this does not mean that there is no solution to your main problem, just blind action is not the way to do it. I would advise you to ask a second question, in which you specifically explain what you are trying to achieve (for example, mocking the network component in tests), and you will probably get several alternative solutions that will get you there.

0
source

All Articles