【问题标题】:Mock ExecutorService and Lambda expression for unit test in java模拟 ExecutorService 和 Lambda 表达式,用于 java 中的单元测试
【发布时间】:2019-02-15 14:12:29
【问题描述】:

我的代码库与此类似,基于输入参数,我使用 lambda 表达式创建对象。 (我之所以使用 lambda 表达式来并行创建对象是因为对象创建操作成本很高)。

private List<Future<MyObj1>> myObj1FutureList = new ArrayList<>();
 for (String key : keys) {
  Future<MyObj1> myObj1Future = executorService.submit(() -> new MyObj1(AnyObject, Arrays.asList(key),"AnyString",AnyObject,null,AnyObject));
  myObj1FutureList.add(myObj1Future);
            }

我正在为此编写单元测试用例。我必须在其中模拟 executor 服务以及 lambda 表达式。 我正在使用类似的测试用例

    Future<MyObj1> myObj1Future1 = mock(Future.class);
    MyObj1 myObj1 = mock(MyObj1.class);
    when(myObj1Future1.get()).thenReturn(myObj1);
    PowerMockito.whenNew(MyObj1.class).withArguments(eq(obj1), eq(Arrays.asList(myObj1)), anyString(), any(),any(), any()).thenReturn(myObj1);
    when(executorService.submit(() -> myObj1)).thenReturn(myObj1Future1);

但我观察到,模拟对象的值即将为空。 我在这里错过了什么吗?请建议。

为了补充更多信息,MyObj1 在构造函数中有 6 个参数。 注意:虽然 powermockito 的使用成本很高,但我只看到了这个可能的选项。 请提出任何其他可能的选择。

【问题讨论】:

  • 最好正确格式化您发布的代码以使其更易于阅读和理解。
  • 我的坏。由于隐私问题而更改名称时,我忘记重新格式化。
  • 模拟FutureMyObj1 是不是有点过头了? Future 的任何实现本身都是一个非常简单的类,它不依赖任何昂贵或外部的东西。如果是 POJO,MyObj1 也一样。
  • MyObj1 不是 POJO。它有一些复杂的对象。对于某些对象,它对依赖图进行服务调用并获取数据。所以,在单元测试中,我也必须模拟它。

标签: java unit-testing mockito executorservice powermockito


【解决方案1】:

您的测试过于复杂。

它应该是这样的:

MyObj1 result1 = new MyObj1(...); // Use whatever parameters you want.
MyObj1 result2 = new MyObj1(...); // Use whatever parameters you want.
Future<MyObj1> future1 = CompletableFuture.completedFuture(result1);
Future<MyObj1> future2 = CompletableFuture.completedFuture(result2);
when(executorService.submit(Mockito.<Callable<MyObj1>>any()))
  .thenReturn(future1, future2);

凭经验得出的规则:

  • 不要模拟您的 pojo 或类似 pojo 的构造(MyObj1Future)。
  • 使用更复杂对象的最基本的类似 pojo 的项目。在Future 的情况下,它是CompletableFuture.completedFuture(obj)

【讨论】:

  • 我已经创建了 MyObj1 的 Mock,因为在实际代码中,它会调用其他微服务并获取数据。所以在测试中,我必须避免这种情况。
  • 你在测试什么? MyObj1 或其他课程?如果您正在测试MyObj1,则应该将其包裹在Future 中。如果没有,就嘲笑它:MyObj1 obj = mock(MyObj1.class);。如果因为参数而不能,请从 MyObj1 类中提取一个接口并模拟该接口。
  • 我同意,我需要测试类而不是对象。我尝试过这种方法。但不工作。方法没有被嘲笑。我想,由于在执行器服务的提交中,lambda 表达式就在那里。这就是它不起作用的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多