Robolectric/Mockito给出错误'when()需要一个必须'a method call on a mock'的参数,但它是一个模拟



实际上,问题比标题更奇怪。我有两个测试,我看不出它们之间的区别。在一个我做

when(context.getPackageManager()).thenReturn(packageManager);

而且效果很好。我在另一个人身上做了同样的事情,却犯了错误。

以下是成功的测试:

@RunWith(RobolectricTestRunner.class)

@LooperMode(LooperMode.Mode.PAUSED(@Config(sdk=Build.VERSION_CODES.P(公共类BtScannerLockTests{@规则public MockitoRule MockitoRule=MockitoJUnit.rule((.sstrictness(Stricty.LENIENT(;

@Mock
BluetoothAdapter bluetoothAdapter;
@Mock
BluetoothLeScanner bluetoothLeScanner;
@Mock
PackageManager packageManager;
@Mock
Context context;
@Before
public void setUp() throws Exception {
ShadowLog.stream = System.out;
}
private void setUpMocksForAdapter()
{
BtScanner.testBtleSupport = true;
AndroidBtManager.setBluetoothAdpater(bluetoothAdapter);
when(bluetoothAdapter.isEnabled()).thenReturn(true);
when(bluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
when(bluetoothAdapter.getBluetoothLeScanner()).thenReturn(bluetoothLeScanner);
when(context.getPackageManager()).thenReturn(packageManager);
when(packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)).thenReturn(true);
}
private long startTime = 0;
private long time = 0;
private ScannerCountDownLatch countDownLatch;
private int btDiscoveryTime;
private int btleScanTime;
@Test
public void testBtScannerCycle_BtleScanlength() throws InterruptedException
{
StatusEventCallback statusEventCallback = new StatusEventCallback()
{
@Override
public void onStatusEvent(StatusEvent statusEvent, PhdInformation phdInformation)
{
System.out.println("Status event " + statusEvent.name());
switch(statusEvent)
{
case BTLE_SCAN_STARTED:
startTime = System.currentTimeMillis();
break;
case CLASSIC_SCAN_STARTED:
time = System.currentTimeMillis() - startTime - btleScanTime;
startTime = System.currentTimeMillis();
countDownLatch.countDown();
break;
}
}
};
btDiscoveryTime = 1000;
btleScanTime = 10000;
Context context = ApplicationProvider.getApplicationContext();
setUpMocksForAdapter();
AndroidBtManager.setStatusEventCallback(statusEventCallback);
BtScanner.setScanTimes(btDiscoveryTime, btleScanTime);
BtScanner btScanner = new BtScanner(context, bluetoothAdapter);
startTime  = System.currentTimeMillis();
countDownLatch = new ScannerCountDownLatch(2);
btScanner.start();
shadowOf(Looper.getMainLooper()).idle();
if(countDownLatch.await(15, TimeUnit.SECONDS)) // Assert length of btle scan time 1
{
assertTrue((time > -50 && time < 50));
countDownLatch = new ScannerCountDownLatch(1);
if(countDownLatch.await(15, TimeUnit.SECONDS))  // Assert length of btle scan time 2
{
assertTrue((time > -50 && time < 50));
}
else // Timeout
{
fail();
}
}
else  // Timeout
{
fail();
}
btScanner.terminateScan();
assertFalse(btScanner.isBtScannerRunning());
}

这个测试有点复杂,但重要的是在"setUpMocksForAdapter(("中。它运行良好。失败的测试更简单,因为它还没有完成,而且还没有断言。

@RunWith(RobolectricTestRunner.class)
@LooperMode(LooperMode.Mode.PAUSED)
@Config(sdk = Build.VERSION_CODES.P)
public class ProprietaryDriverMonitorTests
{
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.LENIENT);
@Mock
Intent intent;
@Mock
ResolveInfo resolveInfo1;
@Mock
ResolveInfo resolveInfo2;
@Mock
PackageManager packageManager;
@Mock
Context context;
@Before
public void setUp() throws Exception {
ShadowLog.stream = System.out;
context = ApplicationProvider.getApplicationContext();
ContinuaHandlerThread.isUnitTesting = true;
}
private List<ResolveInfo> matches = new ArrayList<>();
@Test
public void testBasicCycle() throws Exception
{
setUp();
matches.clear();
matches.add(resolveInfo1);
matches.add(resolveInfo2);
when(context.getPackageManager()).thenReturn(packageManager);
when(packageManager.queryIntentServices(intent, 0)).thenReturn(matches);
//resolveInfo1.serviceInfo.packageName
AndroidBtManager androidBtManager = new AndroidBtManager(context, false, false, true);
ProprietaryDriverMonitor proprietaryDriverMonitor =
new ProprietaryDriverMonitor(androidBtManager, context, 5);
proprietaryDriverMonitor.start();
Thread.sleep(20000);
}

当我执行"when(context.getPackageManager(((.thenReturn(packageManager(;"时,此测试会失败我不明白为什么这个测试失败,而另一个测试没有。我在测试2中做错了什么,而我在测试1中做得对?

我想Robolectric的Mocks不是热门话题。在任何情况下,答案都是mock(在本例中为Context(被生成上下文的另一个调用覆盖。该上下文的初始Mock在重写它的调用之前一直存在。在一个测试中,重写调用在给定检查之前完成,在另一种情况下,在给定检查之后完成。

在复杂的单元测试中很难看到,但当涉及蓝牙连接时,很难编写简单的单元测试。我发现不可能测试某些功能,因为Android或库会覆盖我在测试过程中需要执行的任何Mock。

最新更新