9

我需要模拟一些自定义类(为它创建一个阴影)。我已经阅读了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. 使用 Robolectric 自定义阴影类模拟本机方法

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

  • InstrumentingClassLoaderConfig未找到
  • Setup未找到

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

4

2 回答 2

5

应避免自定义阴影,并且必须是最后的手段。仅当您无法对代码进行大量重构时才应使用它,这会阻止您像本机方法调用一样运行测试。最好使用 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 运行的任何测试用例。

于 2015-08-12T15:17:50.250 回答
3

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

首先感谢您检查我的代码。我对 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(最新)版本,只需在标题中指定影子类就足够了。

我希望它有帮助

于 2016-07-18T12:28:44.437 回答