如何用自定义 class 覆盖 Robolectric 标准阴影 class?

How to override Robolectric standard shadow class with custom class?

我正在编写一个连接低功耗蓝牙设备的简单应用程序。连接到设备的代码位于 HandlerThread 上,因此,为了使处理程序线程在我使用的单元测试中工作 robolectric.

使用robolectric后,handler线程运行正常,但又出现了另一个问题。

Robolectric 不允许我模拟 BluetoothDevice class 因为 robolectric ShadowBluetoothDevice class 不包含该方法 connectGatt(...)。所以,在运行时我得到错误:

java.lang.NoSuchMethodError: android.bluetooth.BluetoothDevice.connectGatt(Landroid/content/Context;ZLandroid/bluetooth/BluetoothGattCallback;)Landroid/bluetooth/BluetoothGatt;

at com.example.BLEGattTest.setup(BLEGattTest.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.robolectric.RobolectricTestRunner.evaluate(RobolectricTestRunner.java:250)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:176)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:49)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner.evaluate(RobolectricTestRunner.java:142)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

所以,我在想,如果我可以重写 ShadowBluetoothDevice,我真的可以做到这一点吗?

我的代码:

@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
    public class BLEGattTest {

        private BLEGattScanner scanner;

        private Customer customer;

        private BluetoothDevice device;

        @Before
        public void setup(){

            customer = new Customer();
            customer.setDevice(device);

            device = Mockito.mock(BluetoothDevice.class);
            when(device.connectGatt(any(Context.class), anyBoolean(), any(BluetoothGattCallback.class))).thenReturn(null);

            scanner = new BLEGattScanner(RuntimeEnvironment.application);
            scanner.start();
        }

        @After
        public void tearDown() throws InterruptedException {
            if(scanner != null){
                scanner.stopThread();
                scanner.join(1000);
            }
        }

        @Test
        public void testMocks(){
            Assert.assertEquals("asdf", device.getName());
        }
    }

您添加设备,然后模拟它。那行不通-您需要模拟它然后设置设备。

customer.setDevice(device) 时,设备未定义。