我有一个RealmManager类,我有几个方法来执行CRUD。这是我在这个课程中的save
方法。
public void save(final List<PointOfInterest> pointOfInterestList) {
if (mRealm == null || pointOfInterestList == null || pointOfInterestList.isEmpty()) {
return;
}
mRealm.executeTransaction(new Realm.Transaction() { // <= line 155, java.lang.NullPointerException points to this line
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(pointOfInterestList);
}
});
}
我写了一个junit测试来测试它。
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 19)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@SuppressStaticInitializationFor("io.realm.internal.Util")
@PrepareForTest({Realm.class, RealmLog.class})
public class RealmPOIManagerTest
{
@Rule
public PowerMockRule rule = new PowerMockRule();
private Realm mockRealm;
@Before
public void setUp() throws Exception
{
mockStatic(RealmLog.class);
mockStatic(Realm.class);
Realm mockRealm = PowerMockito.mock(Realm.class);
when(Realm.getDefaultInstance()).thenReturn(mockRealm);
this.mockRealm = mockRealm;
}
@Test
public void shouldVerifyThatPOIWasCreated() {
List<PointOfInterest> poiList = new ArrayList<>(1);
doCallRealMethod().when(mockRealm).executeTransaction(Mockito.any(Realm.Transaction.class));
PointOfInterest pointOfInterest = mock(PointOfInterest.class);
when(mockRealm.createObject(PointOfInterest.class)).thenReturn(pointOfInterest);
poiList.add(pointOfInterest);
RealmPOIManager.getInstance().save(poiList);
// Verify that Realm#createObject was called only once and
// Verify that a PointOfInterest was in fact created.
verify(mockRealm, times(1)).insertOrUpdate(poiList);
}
@Test
public void shouldVerifyCRUD()
{
List<PointOfInterest> poiList = getCollectionOfPOIs();
// Create list elements
RealmPOIManager.getInstance().save(poiList); // <= line 112
// Read a POI item from db based on id
PointOfInterest result = RealmPOIManager.getInstance().loadPOIByBookingId("1");
// Make sure retrieved POI is as same as the original item
assertThat(poiList.get(0), is(result));
// Update POI, save it and make sure the item has been updated
result.setUid("4");
List<PointOfInterest> list = new ArrayList<>(1);
list.add(result);
RealmPOIManager.getInstance().save(list);
PointOfInterest result2 = RealmPOIManager.getInstance().loadPOIByBookingId("4");
assertThat(result, is(result2));
PointOfInterest result3 = RealmPOIManager.getInstance().loadPOIByBookingId("1");
assertNull(result3);
}
private List<PointOfInterest> getCollectionOfPOIs()
{
List<PointOfInterest> poiList = new ArrayList<>(3);
PointOfInterest poi1 = new PointOfInterest();
poi1.setUid("1");
PointOfInterest poi2 = new PointOfInterest();
poi2.setUid("2");
PointOfInterest poi3 = new PointOfInterest();
poi3.setUid("3");
poiList.add(poi1);
poiList.add(poi2);
poiList.add(poi3);
return poiList;
}
}
第一个测试shouldVerifyThatPOIWasCreated
成功通过而第二个测试失败。这是日志中的内容:
java.lang.NullPointerException
at io.realm.BaseRealm.beginTransaction(BaseRealm.java:337)
at io.realm.Realm.beginTransaction(Realm.java:122)
at io.realm.Realm.executeTransaction(Realm.java:1087)
at com.my.package.db.dao.RealmPOIManager.save(RealmPOIManager.java:155)
at com.my.package.sdk.db.dao.RealmPOIManagerTest.shouldVerifyCRUD(RealmPOIManagerTest.java:112)
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$1.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.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:65)
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.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1873)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:773)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:638)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:98)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78)
at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:57)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
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:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
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)
Process finished with exit code 255
这是我的PointOfInterest类的一部分。
@Parcel
@RealmClass
public class PointOfInterest implements RealmModel {
public static final String REALM_KEY_UID = "uid";
@Required // Throw exception if BookingId is `null`
@PrimaryKey
String uid;
...
}
答案 0 :(得分:1)
Realm在单元测试中不起作用。 Realm的github上的单元测试示例显示Realm被模拟,因为Realm在Android之外不起作用。
要测试特定于Realm的行为,您需要使用检测测试。
(这实质上意味着
doCallRealMethod().when(mockRealm).executeTransaction(Mockito.any(Realm.Transaction.class));
这不起作用,在非Android JVM上下文中调用的实际方法将失败。)
答案 1 :(得分:0)
您需要在List<PointOfInterest> pointOfInterestList
内再次提取public void execute(Realm realm)
。
mRealm.executeTransaction(new Realm.Transaction() { // <= line 155, java.lang.NullPointerException points to this line
@Override
public void execute(Realm realm) {
// fetch objects
List<PointOfInterest> poiList = realm.where.....
realm.insertOrUpdate(poiList);
}
});