Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 机器人分子测试中Android活动中的模拟字段_Java_Android_Unit Testing_Mockito_Robolectric - Fatal编程技术网

Java 机器人分子测试中Android活动中的模拟字段

Java 机器人分子测试中Android活动中的模拟字段,java,android,unit-testing,mockito,robolectric,Java,Android,Unit Testing,Mockito,Robolectric,因此,我正在使用遗留代码,我想对其中一个更简单的屏幕进行单元测试,即登录。 我没有任何DI框架 我使用robolectric 4.0.1和mockito 1.10.19 目前,由于我试图模拟的对象上存在空指针,我的测试失败: 测试类 @RunWith(RobolectricTestRunner.class) public class LoginActivityTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.ru

因此,我正在使用遗留代码,我想对其中一个更简单的屏幕进行单元测试,即登录。 我没有任何DI框架

我使用robolectric 4.0.1和mockito 1.10.19

目前,由于我试图模拟的对象上存在空指针,我的测试失败:

测试类

@RunWith(RobolectricTestRunner.class)
public class LoginActivityTest {
    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Mock
    FirebaseInstanceId firebaseInstanceId;

    @InjectMocks
    private LoginActivity activity;

    @Before
    public void setup() {

        when(firebaseInstanceId.getToken()).thenReturn("mockToken");
        ActivityController<LoginActivity> activityController = Robolectric.buildActivity(LoginActivity.class);
        activity = activityController.get();
        initMocks(this);
        activityController.create();
    }

    @Test
    public void checkThatLoginButtonExists() {
        // does not reach this point
        Button btn = (Button) activity.findViewById(R.id.button_login);

        assertNotNull("Button exisits", btn);
    }
}
我主要是根据google的发现,在我的TestClass中重新排序指令,但似乎没有任何效果。 据我所知,调用getFireBaseInstanceId方法时,firebaseInstanceId不应为null,因为它在setup方法期间被注入initMocksthis

这适用于其他测试,但没有一个真正结合了robolectric和mockito

编辑1: 我已经将initMocksthis作为设置的第一行 我添加了一些System.out.println来看看会发生什么,我注意到LoginActivity构造函数会多次被调用,一次用于initmock,一次用于roblectric.buildActivity

编辑2: 我已将测试类中的设置更改如下

private void setMyOwnMock(String fieldName, Object inClass, Object mock ){
        Field declaredField;
        try {
            declaredField = inClass.getClass().getDeclaredField(fieldName);
            declaredField.setAccessible(true);
            declaredField.set(inClass, firebaseInstanceId);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Before
    public void setup() {
        ActivityController<LoginActivity> activityController = Robolectric.buildActivity(LoginActivity.class);
        activity = activityController.get();

        setMyOwnMock("firebaseInstanceId", activity, firebaseInstanceId);

        when(firebaseInstanceId.getToken()).thenReturn("mockToken");

//        System.out.println(activity.firebaseInstanceId == null);

        activityController.create();
    }

虽然可能没有我想要的那么干净,但它可以在不更改生产代码的情况下完成工作。

在这种情况下,注入和自动创建将不起作用。这:

@InjectMocks
private LoginActivity activity;
在设置中被以下内容覆盖:

ActivityController<LoginActivity> activityController = 
   Robolectric.buildActivity(LoginActivity.class);
activity = activityController.get();

然后我仍然得到默认的FirebaseApp在此过程中未初始化null。确保首先调用FirebaseApp.initializeAppContext。这是一个非法的状态异常,因为在Robolectric.buildActivity期间引发的getFirebaseInstanceId调用中firebaseInstanceId为null?这可能会起作用,我会尝试一下,但这意味着我更改生产代码仅仅是为了单元测试,这让我感到不舒服,特别是现在它停在firebase上,但以后可能会挂在其他地方。
ActivityController<LoginActivity> activityController = 
   Robolectric.buildActivity(LoginActivity.class);
activity = activityController.get();
@Before
public void setup() {
        initMocks(this);
        when(firebaseInstanceId.getToken()).thenReturn("mockToken");
        ActivityController<LoginActivity> activityController = 
            Robolectric.buildActivity(LoginActivity.class);
        activity = activityController.get();
        activity.setFirebaseInstanceId(firebaseInstanceId);         
        activityController.create();