【问题标题】:Why are my Robolectric tests failing when using RealmResults?为什么我的 Robolectric 测试在使用 RealmResults 时会失败?
【发布时间】:2017-03-01 12:38:28
【问题描述】:

我在我的项目中使用 Realm,并且在试图让测试正常运行时遇到了一场噩梦。在您开始使用 RealmResults 从数据库中取出东西之前,我已经完成了所有测试。下面的代码是我得到结果的方式

private void getUser(){
    realm.beginTransaction();
    RealmResults<User> realmUsers = realm.where(User.class).findAll();
    user = realmUsers.first();
    realm.commitTransaction();
    Log.d("Test", user.getFirstName() + " " + user.getLastName());
}

只需返回存储在 Realm 中的所有结果。下面是测试完整的单元测试。

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP, manifest = "src/main/AndroidManifest.xml")
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareForTest({Realm.class, RealmConfiguration.class,
        RealmQuery.class, RealmResults.class, RealmCore.class, RealmResults.class})
public class SecondActivityTest {

    @Rule
    public PowerMockRule rule = new PowerMockRule();

    private SecondActivity activity;

    private RealmResults<User> realmUsers;

    @Before
    public void setUp(){
    MockitoAnnotations.initMocks(this);

    // Setup Realm + Mock
    mockStatic(Realm.class);
    mockStatic(RealmConfiguration.class);
    mockStatic(RealmCore.class);
    mockStatic(RealmQuery.class);

    final Realm mockRealm = mock(Realm.class);
    doNothing().when(RealmCore.class);
    RealmCore.loadLibrary(any(Context.class));

    when(Realm.getDefaultInstance()).thenReturn(mockRealm);
    when(mockRealm.createObject(User.class)).thenReturn(new User());

    User userOne = new User("Matt", "Dunn");
    User userTwo = new User("Michael", "Stoddart");

    List<User> userList = Arrays.asList(userOne, userTwo);

    RealmQuery<User> realmQuery = mockRealmQuery();
    RealmResults<User> mockResults = mockRealmResults();

    when(mockResults.iterator()).thenReturn(userList.iterator());
    when(mockResults.size()).thenReturn(userList.size());

    when(mockResults.first()).thenReturn(userList.get(0));

    activity = Robolectric.setupActivity(SecondActivity.class);
}

    @Test
    public void checkActivityNotNull(){
        Assert.assertNotNull(activity);   
    }

    @SuppressWarnings("unchecked")
    private <T extends RealmObject> RealmQuery<T> mockRealmQuery() {
        return mock(RealmQuery.class);
    }

    @SuppressWarnings("unchecked")
    private <T extends RealmObject> RealmResults<T> mockRealmResults() {
        return mock(RealmResults.class);
    }
}

但是,即使我遵循了领域本身提供的指南,这仍然会引发以下异常

https://github.com/realm/realm-java/blob/master/examples/unitTestExample/src/test/java/io/realm/examples/unittesting/ExampleActivityTest.java

Method threw 'org.mockito.exceptions.misusing.NotAMockException' exception. Cannot evaluate io.realm.Realm$$EnhancerByMockitoWithCGLIB$$61d46d71.toString()

我是否错误地嘲笑了 RealmResults?还是完全不同的东西?

编辑:

测试失败时提供的完整堆栈跟踪是

java.lang.NullPointerException
    at com.example.mathewdunn.realmtest.activity.SecondActivity.getUser(SecondActivity.java:34)
    at com.example.mathewdunn.realmtest.activity.SecondActivity.onCreate(SecondActivity.java:29)
    at android.app.Activity.performCreate(Activity.java:5933)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:195)
    at org.robolectric.util.ActivityController$1.run(ActivityController.java:122)
    at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:304)
    at org.robolectric.shadows.CoreShadowsAdapter$2.runPaused(CoreShadowsAdapter.java:45)
    at org.robolectric.util.ActivityController.create(ActivityController.java:118)
    at org.robolectric.util.ActivityController.create(ActivityController.java:129)
    at org.robolectric.util.ActivityController.setup(ActivityController.java:210)
    at org.robolectric.Robolectric.setupActivity(Robolectric.java:46)
    at com.example.mathewdunn.realmtest.SecondActivityTest.setUp(SecondActivityTest.java:83)
    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.RunBefores.evaluate(RunBefores.java:24)
    at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:83)
    at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1899)
    at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:801)
    at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:666)
    at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
    at org.powermock.classloading.AbstractClassloaderExecutor.getResult(AbstractClassloaderExecutor.java:69)
    at org.powermock.classloading.AbstractClassloaderExecutor.executeWithClassLoader(AbstractClassloaderExecutor.java:59)
    at org.powermock.classloading.SingleClassloaderExecutor.execute(SingleClassloaderExecutor.java:67)
    at org.powermock.classloading.AbstractClassloaderExecutor.execute(AbstractClassloaderExecutor.java:43)
    at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:75)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

调试测试时出现 NotAMock 异常。

编辑编辑:

进行一些更改后,现在抛出了一个替代异常。

com.thoughtworks.xstream.converters.ConversionException: Cannot convert type org.apache.tools.ant.Project to type org.apache.tools.ant.Project
---- Debugging information ----
message             : Cannot convert type org.apache.tools.ant.Project to type org.apache.tools.ant.Project
class               : org.apache.tools.ant.Project$1
required-type       : org.apache.tools.ant.Project$1
converter-type      : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
path                : /org.powermock.modules.junit4.rule.PowerMockStatement$1/outer-class/fNext/next/outer-class/outer-class/dependencyResolver/dependencyResolver/project/isLoggingMessage/outer-class
line number         : 230
class[1]            : org.apache.tools.ant.Project
class[2]            : org.robolectric.internal.dependency.MavenDependencyResolver
class[3]            : org.robolectric.internal.dependency.CachedDependencyResolver
class[4]            : org.robolectric.RobolectricGradleTestRunner
class[5]            : org.robolectric.RobolectricTestRunner$HelperTestRunner
class[6]            : org.robolectric.RobolectricTestRunner$HelperTestRunner$1
class[7]            : org.junit.internal.runners.statements.RunBefores
class[8]            : org.powermock.modules.junit4.rule.PowerMockStatement
class[9]            : org.powermock.modules.junit4.rule.PowerMockStatement$1
version             : not available
-------------------------------

    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:456)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:503)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:429)
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:281)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:70)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
    at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
    at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
    at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1230)
    at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1214)
    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1085)
    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1076)
    at org.powermock.classloading.DeepCloner.clone(DeepCloner.java:55)
    at org.powermock.classloading.AbstractClassloaderExecutor.executeWithClassLoader(AbstractClassloaderExecutor.java:56)
    at org.powermock.classloading.SingleClassloaderExecutor.execute(SingleClassloaderExecutor.java:67)
    at org.powermock.classloading.AbstractClassloaderExecutor.execute(AbstractClassloaderExecutor.java:43)
    at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:75)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:265)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:191)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:56)
    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:157)
    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)

干杯

【问题讨论】:

  • 请包含整个堆栈跟踪。某个地方正在调用 Realm.toString()
  • 现在将编辑帖子@Kiskae
  • 我可以建议您将活动中的数据层交互提取到另一个类中吗?测试设置表明您正在测试非常复杂的系统
  • @EugenMartynov 我通常使用 MVP,这只是一个测试项目,试图让它工作,你认为使用 MVP 对我有好处吗?
  • Cannot convert type org.apache.tools.ant.Project to type org.apache.tools.ant.Project 这是an error in Robolectric 3.1 and 3.2, but will be fixed in 3.3 quite soon? 半年前还不是“很快”,所以你应该高兴。

标签: java android mockito realm robolectric


【解决方案1】:

不完整的模拟

Realm test example 中缺少这些行:

    // The for(...) loop in Java needs an iterator, so we're giving it one that has items,
    // since the mock RealmResults does not provide an implementation. Therefore, anytime
    // anyone asks for the RealmResults Iterator, give them a functioning iterator from the
    // ArrayList of Persons we created above. This will allow the loop to execute.
    when(people.iterator()).thenReturn(personList.iterator());

    // Return the size of the mock list.
    when(people.size()).thenReturn(personList.size());

解释在代码注释中 - 基本上 RealmResults 就像一个 Realm 'Cursor' 并且不包含任何数据本身,但作为存储在 Realm 中的对象的代理。

考虑到这个事实,一个模拟实例没有任何迭代器,很明显你必须重定向你在这个 RealmResults 上的迭代到一个不同的、功能齐全的 List 实例 - @987654324 @在你的情况下:

    when(mockResults.iterator()).thenReturn(userList.iterator());
    when(mockResults.size()).thenReturn(userList.size());

这将允许您迭代并获取模拟的 RealmResults 实例的大小。

由于您在 getUser() 方法中的 RealmResults 上调用 first(),因此您也需要模拟此方法:

    when(mockResults.first()).thenReturn(userList.get(0));

另外,请注意,在您的 getUser() 方法中调用 realm.beginTransaction()realm.commitTransaction() 是多余的,因为您没有执行任何写入操作。您可以安全地删除它们,或者也可以模拟它们:

    doCallRealMethod().when(mockRealm).beginTransaction();
    doCallRealMethod().when(mockRealm).commitTransaction();

【讨论】:

  • 我已经添加了您建议的两个语句以及更多语句,现在我得到了另一个空指针。 when(mockRealm.where(User.class).findAll()).thenReturn(mockResults);
  • @drofnnuD 错误是什么?另外,现在尝试删除所有 when(realmQuery... 调用,因为您还不需要它们 - 也许您不小心用它们重新定义了模拟
  • @drofnnuD 查看我对模拟 realmUsers.first() 调用的编辑
  • 我已经进行了您建议的编辑并更新了主要问题,因此这是当前正在运行的测试方法。它仍然失败,抛出我在主要问题正文中发布的相同 NullPointer
  • @drofnnuD beginTransaction()commitTransaction() 怎么样?您是否尝试过删除它们,或者使用 doCallRealMethod().when(mockRealm.beginTransaction())doNothing().when(mockRealm.beginTransaction()) 等来模拟它们?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多