Merge pull request #3197 from brettchabot/shadowBtDevice156191900

[ShadowBluetoothDevice] Override the constructor for BluetoothDevice to
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothDeviceTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothDeviceTest.java
new file mode 100644
index 0000000..e691fe4
--- /dev/null
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothDeviceTest.java
@@ -0,0 +1,26 @@
+package org.robolectric.shadows;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import android.bluetooth.BluetoothDevice;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.TestRunners;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(TestRunners.MultiApiSelfTest.class)
+public class ShadowBluetoothDeviceTest {
+
+  private static final String MOCK_MAC_ADDRESS = "00:11:22:33:AA:BB";
+
+  @Test
+  public void canCreateBluetoothDeviceViaReflection() throws Exception {
+    // This test passes as long as no Exception is thrown. It tests if the constructor can be
+    // executed without throwing an Exception when getService() is called inside.
+    BluetoothDevice bluetoothDevice =
+        ReflectionHelpers.callConstructor(
+            BluetoothDevice.class,
+            ReflectionHelpers.ClassParameter.from(String.class, MOCK_MAC_ADDRESS));
+    assertThat(bluetoothDevice).isNotNull();
+  }
+}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothDevice.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothDevice.java
index 0de44f1..9e6a3c4 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothDevice.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothDevice.java
@@ -1,6 +1,9 @@
 package org.robolectric.shadows;
 
+import static org.robolectric.shadow.api.Shadow.directlyOn;
+
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetooth;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -9,6 +12,23 @@
 
   private String name;
 
+  /**
+   * Implements getService() in the same way the original method does, but ignores any Exceptions
+   * from invoking {@link BluetoothAdapter#getBluetoothService}.
+   */
+  @Implementation
+  public static IBluetooth getService() {
+    // Attempt to call the underlying getService method, but ignore any Exceptions. This allows us
+    // to easily create BluetoothDevices for testing purposes without having any actual Bluetooth
+    // capability.
+    try {
+      return directlyOn(BluetoothDevice.class, "getService");
+    } catch (Exception e) {
+      // No-op.
+    }
+    return null;
+  }
+
   public void setName(String name) {
     this.name = name;
   }