【问题标题】:How to create custom shadows in robolectric 3.0?如何在 robolectric 3.0 中创建自定义阴影?
【发布时间】:2015-08-10 13:28:44
【问题描述】:

我需要模拟一些自定义类(为它创建一个影子)。 我已经阅读了http://robolectric.org/custom-shadows/ 如何做到这一点。

所以,我有一些课:

public class MyClass {

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

我创建了一个影子:

@Implements(MyClass.class)
public class MyShadowClass {

  @Implementation
  public static int regularMethod() { return 2; }
}

我在测试类中设置了阴影:

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, shadows={MyShadowClass.class})
public class MyTest {

  @Test
  public void testShadow() {
      assertEquals(2, MyClass.regularMethod());
  }
}

但是没有使用阴影。

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

如何使任何自定义阴影对 RobolectricGradleTestRunner 可见?

我已经试过了:

  1. http://www.codinguser.com/2015/06/how-to-create-shadow-classes-in-robolectric-3/
  2. https://github.com/jiahaoliuliu/RobolectricSample/blob/master/app-tests/src/main/java/com/jiahaoliuliu/robolectricsample/RobolectricGradleTestRunner.java
  3. Mock native method with a Robolectric Custom shadow class

但我得到了各种编译错误,例如

  • InstrumentingClassLoaderConfig 未找到
  • Setup 未找到

如何在 robolectric 3.0 中正确使用自定义阴影?

【问题讨论】:

  • 我们通常将静态方法包装在自己的类中或我们可以在测试中模拟的受保护方法中

标签: android testing robolectric shadows


【解决方案1】:

应避免自定义阴影,并且必须是最后的手段。仅当您无法对代码进行大量重构时才应使用它,这会阻止您像本机方法调用一样运行测试。最好使用 powermock 或 mockito 模拟该类的对象或 spy,而不是自定义隐藏它。如果是静态方法,则使用 powermock。

在我们的项目中,我们有一个包含一些本地方法的类,它是应用程序中随处使用的配置类。所以我们将原生方法移到另一个类并隐藏它。那些原生方法未能通过测试用例。

无论如何,这是在 robolectric 3.0 中自定义阴影的方法:

创建一个扩展 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();
}

确保包不包含您使用 robolectric 运行的任何测试用例。

【讨论】:

    【解决方案2】:

    我是您所指的第二个仓库的创建者佳豪。

    首先感谢您检查我的代码。我对 Android 做了很多研究,我很高兴我的研究对其他人有用。

    然后,关于 Robolectric 的阴影。我在这个项目中使用 Robolectric 3.1,来测试 Robolectric 3 如何与 MarshMallow 一起工作: https://github.com/jiahaoliuliu/robolectricForMarshmallow

    我一直在测试新的运行时权限管理器,以及影子应用程序和活动。

    这里是阴影活动的示例代码:

    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

    这就是我在单元测试中使用它的方式:

    包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

    如您所见,我没有使用自定义的 Gradle Test Runner。我检查了 Robolectric 的源代码,对于 3.0 和 3.1(最新)版本,只需在标题中指定影子类就足够了。

    希望对你有帮助

    【讨论】:

    • 你是如何在 MainActivityTest() 中使用它的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多