Robolectrics BluetoothAdapter gives all null on its methods

174 views
Skip to first unread message

Brian Reinhold

unread,
Mar 4, 2020, 6:54:32 AM3/4/20
to Robolectric
Robolectric says mocks are not needed, but without mocks, Robolectric does nothing. I don't need it but mocks are painful.

Trying to test my Bluetooth Scanner which makes a call to BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner()

No matter what I do I always get this NullPointerException

java.lang.NullPointerException
at android.bluetooth.BluetoothAdapter.getLeState(BluetoothAdapter.java:950)
at android.bluetooth.BluetoothAdapter.getLeAccess(BluetoothAdapter.java:960)
at android.bluetooth.BluetoothAdapter.getBluetoothLeScanner(BluetoothAdapter.java:721)

How can one write units tests that involve Android Bluetooth APIs using Robolectric ... without mocking very single method in the Bluetooth stack? Isn't that the idea of Robolectric?

Here is my test which is an utter failure.

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.lni.codephg.inter.MdsIntermediary;
import com.lni.codephg.inter.MetricIntermediary;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;

import java.util.List;

import static org.robolectric.Shadows.shadowOf;

@RunWith(AndroidJUnit4.class)
//@RunWith(RobolectricTestRunner.class) // makes no difference which runner I use
@Config(sdk = Build.VERSION_CODES.P)
public class BtScannerTests
{
private BluetoothAdapter bluetoothAdapter;
//private final Context context = RuntimeEnvironment.systemContext;

@Before
public void setUp() throws Exception
{
// This does not change anything
PackageManager pm = context.getPackageManager();
shadowOf(pm).setSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE, true);

bluetoothAdapter = Shadow.newInstanceOf(BluetoothAdapter.class);

// Neither does this
shadowOf(bluetoothAdapter).setState(BluetoothAdapter.STATE_ON);
shadowOf(bluetoothAdapter).setEnabled(true);
}

private static boolean done = false;
@Test
public void testBtScannerCycle() throws InterruptedException
{
IntermediaryCallback intermediaryCallback = new IntermediaryCallback()
{
@Override
public void onReceiveMdsIntermediary(MdsIntermediary mds, int connectionHandle)
{

}

@Override
public void onReceiveMetricIntermediaries(List<MetricIntermediary> metricList, MdsIntermediary mds, int connectionHandle)
{

}
};

StatusEventCallback statusEventCallback = new StatusEventCallback()
{
@Override
public void onStatusEvent(StatusEvent statusEvent, int connectionHandle, String btAddress)
{
System.out.println("Status event " + statusEvent.name());
if(statusEvent == StatusEvent.SCANNING_PAUSED);
{
done = true;
}
}
};

Activity activity = Robolectric.buildActivity(Activity.class).get();
Context context = ApplicationProvider.getApplicationContext();
AndroidBtManager.setStatusEventCallback(statusEventCallback);
AndroidBtManager androidBtManager =
new AndroidBtManager(context, intermediaryCallback, false, false, true);
BtScanner btScanner = androidBtManager.getBtScanner();
while(!done)
{
Thread.sleep(1000);
}

}
}

Maks Verver

unread,
Mar 4, 2020, 7:09:56 AM3/4/20
to robol...@googlegroups.com
Hi Brian,

You may be able to use the ShadowBluetoothAdapter, but you'll have to explicitly add it to your test config (e.g. with @Config(shadows={ShadowBluetoothAdapter.class}).

Here's a random example of a test using this shadow:

  - Maks.






--
You received this message because you are subscribed to the Google Groups "Robolectric" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robolectric...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/robolectric/957805bf-fc72-4ab5-9dbd-1a403c53cf51%40googlegroups.com.

Brian Reinhold

unread,
Apr 30, 2020, 12:28:15 PM4/30/20
to Robolectric
Hi Maks,

That may have been the case but I just do ShadowBluetoothAdapter bluetoothAdapter = new ShadowBluetoothAdapter();
It gives me a little, but VERY little. I have an NPE immediately upon bluetoothAdapter.getBluetoothLeScanner(); with no way to set it, shadow it, or do anything. I have seen some methods associated with the deprecated pre-5 LeScanner but that does not do me any good. We are at Android 10 now.

Maybe trying to test Bluetooth with Robolectric is so out of scope/incomplete it is infeasible to do so.

Brian
To unsubscribe from this group and stop receiving emails from it, send an email to robol...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages