How to create custom shadows in robolectric 3.0?

I need to make fun of some custom class (create a shadow for it). I already read http://robolectric.org/custom-shadows/ how to do this.

so i have some class:

public class MyClass { public static int regularMethod() { return 1; } } 

I create a shadow:

 @Implements(MyClass.class) public class MyShadowClass { @Implementation public static int regularMethod() { return 2; } } 

And I set the shadow in the Test-class:

 @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class, shadows={MyShadowClass.class}) public class MyTest { @Test public void testShadow() { assertEquals(2, MyClass.regularMethod()); } } 

But the shadow is not used.

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

How to make any custom shadow visible for RobolectricGradleTestRunner?

I have already tried:

but I get various compilation errors like

  • InstrumentingClassLoaderConfig not found
  • Setup not found

How to use custom shadows in robolectric 3.0 ?

+7
android testing robolectric shadows
source share
2 answers

Custom shadows should be avoided and be the last resort. It should be used only if you cannot do a lot of refactoring in your code, which prevents you from running your tests like calling your own method. It’s better to mock an object of this class or spy using powermock or mockito than a custom shadow. If this is a static method, then use powermock.

In our project, we had a class that had some proprietary methods, and it was a configuration class used everywhere in the application. So we moved our own methods to another class and obscured this. These proprietary methods did not run test cases.

In any case, how can you customize the shadow in robolectric 3.0:

Create your own test runner that extends RobolectricGradleTestRunner:

 public class CustomRobolectricTestRunner extends RobolectricGradleTestRunner { public CustomRobolectricTestRunner(Class<?> klass) throws InitializationError { super(klass); } public InstrumentationConfiguration createClassLoaderConfig() { InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder(); builder.addInstrumentedPackage("com.yourClassPackage"); return builder.build(); } 

Make sure the package does not contain test cases that you use with robolectric.

+5
source share

I am Jiahao, creator of the second repository you are talking about.

First of all, thanks for checking the code. I do a lot of research on Android, and I am glad that my research is useful for someone else.

Then, Shadow of Robolectric. I use Robolectric 3.1 in this project to check how Robolectric 3 works with MarshMallow: https://github.com/jiahaoliuliu/robolectricForMarshmallow

I tested the new runtime permission manager, as well as the shadow application and actions.

Here is a sample shadow activity code:

 import android.content.Context; import com.jiahaoliuliu.robolectricformarshmallow.controller.MainController; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; /** * Created by Jiahao on 7/18/16. */ @Implements(MainController.class) public class MainControllerShadow { public void __constructor__ (Context context) { // Not do anything } @Implementation public String getTextToDisplay(boolean permissionGranted) { return "Test"; } } 

https://github.com/jiahaoliuliu/robolectricForMarshmallow/blob/master/app/src/test/java/com/jiahaoliuliu/robolectricformarshmallow/shadow/MainControllerShadow.java

And this is how I use it in unit test:

package com.jiahaoliuliu.robolectricformarshmallow;

 import com.jiahaoliuliu.robolectricformarshmallow.shadow.MainControllerShadow; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricGradleTestRunner; import org.robolectric.annotation.Config; import static org.junit.Assert.*; /** * Created by Jiahao on 6/30/16. */ @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class, manifest = Config.NONE, application = FoolApplication.class, shadows = { MainControllerShadow.class}, sdk = 18) public class MainActivityTest { private MainActivity mMainActivity; @Before public void setUp() throws Exception { mMainActivity = Robolectric.setupActivity(MainActivity.class); } @After public void tearDown() throws Exception { } @Test public void testOnCreate() throws Exception { // Simple test to know that it works assertTrue(true); } } 

https://github.com/jiahaoliuliu/robolectricForMarshmallow/blob/master/app/src/test/java/com/jiahaoliuliu/robolectricformarshmallow/MainActivityTest.java

As you can see, I am not using the configured Gradle Test Runner. I checked the source code of Robolectric, for versions 3.0 and 3.1 (the latter) it is enough to simply specify the shadow classes in the header.

I hope this helps

+2
source share

All Articles