Robolectric / Mockito выдает ошибку «когда () требуется аргумент, который должен быть« вызовом метода для макета », но это Mock - PullRequest
0 голосов
/ 24 марта 2020

На самом деле проблема страннее, чем название. У меня есть два теста, и я не вижу разницы между ними. В одном я делаю

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

, и он отлично работает. Я делаю то же самое в другом, и получаю ошибку.

Вот успешный тест:

@RunWith(RobolectricTestRunner.class)

@ LooperMode (LooperMode.Mode.PAUSED) @Config (sdk = Build.VERSION_CODES.P) publi c class BtScannerMockTests {@Rule publi c MockitoRule mockitoRule = MockitoJUnit.rule (). Строгость (Strictness.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?

1 Ответ

0 голосов
/ 02 апреля 2020

Полагаю, издевательства над Robolectri c - не популярные темы. В любом случае ответом оказывается, что макет (в данном случае контекст) был переопределен другим вызовом, который генерировал контекст. Первоначальный макет этого контекста сохраняется до тех пор, пока этот вызов не переопределит его. В одном тесте переопределение было сделано до данной проверки, а в другом - после.

Его сложно увидеть в сложных модульных тестах, но сложно написать простые модульные тесты, которые, когда используются соединения Bluetooth , Я обнаружил, что невозможно протестировать определенные функции, потому что Android или библиотека переопределяют любые макеты, которые мне нужно выполнить во время тестируемой процедуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...