【问题标题】:How to use real classes and mockito at the same time?如何同时使用真正的课程和模拟?
【发布时间】:2020-03-05 21:12:21
【问题描述】:

我正在尝试使用 Mockito 运行单元测试,但我有一个辅助方法,我想在其中使用真正的类:

public static Location fromCoordinates(float latitude, float longitude){
    Location result = new Location("");
    result.setLatitude(latitude);
    result.setLongitude(longitude);

    return result;
}

上述方法当前会导致“方法...未模拟”。如here 所述的错误,它提供了有关如何使用默认值的建议,但这对我不起作用,因为这会导致纬度和经度在之后返回 0。

我还尝试在测试开始时添加Mockito.mock(Location.class, CALLS_REAL_METHODS);,但似乎没有效果。

如何配置我的测试以使用真实的 Location 类,同时仍然使用 mockito 来模拟其他类?

[编辑] 对于上下文,这是有问题的单元测试

@Test
public void OpensCenteredInLocation() {

    Location l = Mockito.mock(Location.class, CALLS_REAL_METHODS);

    //When the user starts the app
    LocationManager m = Mockito.mock(LocationManager.class);
    Location initial = LocationHelper.fromCoordinates(10, 15); //<--it fails here
    doReturn(initial).when(m).getLastKnownLocation(any(String.class));
    MyApp main = new MyApp(m);

    //Then it should open with the map centered in the user's location
    Assert.assertEquals(10, main.CameraPosition.longitude, 0);
    Assert.assertEquals(15, main.CameraPosition.longitude, 0);
}

失败时抛出java.lang.RuntimeException: Method setLatitude in android.location.Location not mocked. See http://g.co/androidstudio/not-mocked for details.

【问题讨论】:

  • Mockito 不能模拟静态方法。为此,您需要 PowerMockito 之类的东西。但更大的问题是,您首先要测试什么地方需要模拟 Location 对象?
  • 我不需要模拟位置,这就是问题所在,我需要模拟来让我调用真正的构造函数,“方法...未模拟”消息似乎是由 @ 引起的987654327@电话
  • fromCoordinates 是一个静态方法,因此您根本不需要构造一个新的Location 对象。只需在需要的地方致电Location.fromCoordinates(...)Location 上是否还有其他需要模拟的非静态方法?
  • @Jordan 这正是我的测试正在做的,它在new Location("") 引发异常,这是我编写的fromCoordinates 方法的一部分,我找不到android.location.Location.fromCoordinates 方法,问题中显示的一个是MyApp.LocationHelper.fromCoordinates(我自己的班级)
  • 正如@Jordan 指出的那样,您可能希望为此使用PowerMockito。或者,您将 android 中的 Location 对象替换为您自己的对象。如链接所述,您无法选择使用真实对象进行测试。

标签: java android unit-testing mockito


【解决方案1】:

我认为真正的问题不是因为fromCoordinates 方法是静态的,在我看来真正的问题是因为Location 是一个内置的Android 类。

实际上,当您运行单元测试时,它是在您的计算机上运行的,而不是在 Android 设备上。所以你不能使用内置的 Android 类。

看看android documentation

然后根据这个doc告诉你可以添加到你的build.gradle文件中

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }
}

这可以防止 android 类在您尝试使用它们时抛出异常,但请注意,这样做是为了

更改行为,以便方法返回 null 或零

【讨论】:

  • “你不能使用内置的Android类”,是的,这就是答案,既然你提到了它,我意识到这实际上是在我在问题中添加的链接中描述的,但没有强调关于“它正在您的计算机上运行”它并没有被我理解。
  • 好伙伴,我很乐意帮助你。
猜你喜欢
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
相关资源
最近更新 更多