用mockito监视lambda

o2gm4chl  于 2022-11-08  发布在  其他
关注(0)|答案(3)|浏览(131)

我在编写单元测试时遇到了一个有趣的问题,其中涉及到模拟lambda。

@Test
public void spyingLambda() {
    final Supplier<String> spy = Mockito.spy((Supplier) () -> "1");
    spy.get();
}

运行此测试失败,并出现以下错误:
Mockito不能模仿/窥探,因为:- 最终类
解决上述问题的一个方法是用匿名实现替换lambda:

@Test
public void spyingAnonymousImplementation() {
    final Supplier<String> spy = Mockito.spy(new Supplier<String>() {
        @Override
        public String get() {
            return "1";
        }
    });
    spy.get();
}

尽管两个测试完全相同(IDE甚至建议将匿名实现替换为lambda),但第二个测试并没有失败。
我想知道这是不是一个已知的问题,可以在mockito中修复,或者有没有其他的变通办法。

41zrol4v

41zrol4v1#

处理此问题的另一种方法如下:

/**
 * This method overcomes the issue with the original Mockito.spy when passing a lambda which fails with an error
 * saying that the passed class is final.
 */
@SuppressWarnings("unchecked")
static <T, P extends T> P spyLambda(Class<T> lambdaType, P lambda) {
    return (P) mock(lambdaType, delegatesTo(lambda));
}

它允许通过如下更改第一个方法来监视lambda:

@Test
void spyingLambda() {
    Supplier<String> spy = spyLambda(Supplier.class, () -> "1");
    spy.get();
}

希望上面的例子可以帮助其他遇到同样问题的人。

hgc7kmma

hgc7kmma2#

只是为了参考,为了改进@亚历克斯的回答,你还可以做

public static <T> T spyLambda(final T lambda) {
    Class<?>[] interfaces = lambda.getClass().getInterfaces();
    MatcherAssert.assertThat(interfaces, IsArrayWithSize.arrayWithSize(1));
    return Mockito.mock((Class<T>) interfaces[0], delegatesTo(lambda));
}

然后在不指定类型(例如Supplier.class)的情况下简单地探查它

Callable<Integer> callable = spyLambda(() -> {
    return 42;
});
Supplier<Integer> supplier = spyLambda(() -> 42);
Runnable runnable = spyLambda(() -> System.out.println("42"));
d5vmydt9

d5vmydt93#

您可以允许final类模拟。创建文件src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker,其中包含

mock-maker-inline

https://www.baeldung.com/mockito-final#configure-mocktio

相关问题