首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Mockito测试java 8 lambda Consumer API

Mockito测试java 8 lambda Consumer API
EN

Stack Overflow用户
提问于 2018-05-06 19:40:43
回答 3查看 4.8K关注 0票数 8

我需要用lambda Consumer测试一个使用另一个接口作为依赖注入的类。

代码语言:javascript
复制
@Builder
public class Interactor {

    private final Gateway gateway;

    void process(String message, Consumer<String> response){
        gateway.process(message, uuid -> {
            response.accept(uuid.toString());
        });
    }
}

依赖关系的定义如下:

代码语言:javascript
复制
public interface Gateway {

    void process(String message, Consumer<UUID> uuid);
}

我如何模拟网关,以便为我的测试提供UUID值响应?

这就是我到目前为止所尝试的:

代码语言:javascript
复制
@Test
void whillReturnTheInjectedUUIDValueTest() {

    UUID uuid = UUID.randomUUID();

    Gateway gateway = Mockito.mock(Gateway.class);
    Mockito.when(gateway.process("ignored", uuid1 -> {return uuid;}));

    Interactor.builder().gateway(gateway).build().process("ignored", s -> {
        Assertions.assertEquals(uuid.toString(), s);
    });
}

我应该如何向消费者提供返回值?

EN

回答 3

Stack Overflow用户

发布于 2018-05-13 03:37:12

这一次成功了

代码语言:javascript
复制
@Test
void willReturnTheInjectedUUIDValueTest() {

    UUID uuid = UUID.randomUUID();
    Gateway gateway = Mockito.mock(Gateway.class);

    doAnswer(ans -> {
        Consumer<UUID> callback = (Consumer<UUID>) ans.getArgument(1);
        callback.accept(uuid);
        return null;
    }).when(gateway).process(Mockito.any(String.class), Mockito.any(Consumer.class));

    Interactor.builder().gateway(gateway).build().process("ignored", s -> {
        Assertions.assertEquals(uuid.toString(), s);
    });
}

这个答案是-> https://stackoverflow.com/a/47226374/148397的提示

票数 4
EN

Stack Overflow用户

发布于 2018-05-06 20:59:41

现在,我最终在没有Mockito的情况下嘲笑了我自己的内部类。

代码语言:javascript
复制
class InteractorTest {

    @Test
    void whillReturnTheInjectedUUIDValueTest() {

        UUID uuid = UUID.randomUUID();

        Gateway gateway = GatewayMock.builder().value(uuid).build();

        Interactor.builder().gateway(gateway).build().process("ignored", s -> {
            Assertions.assertEquals(uuid.toString(), s);
        });
    }

    @Builder
    private static class GatewayMock implements Gateway {

        private final UUID value;

        @Override
        public void process(String message, Consumer<UUID> uuid) {
            uuid.accept(value);
        }

    }
}
票数 1
EN

Stack Overflow用户

发布于 2018-05-07 06:59:13

你想要什么..。

是为了验证Interactor#process逻辑的结果,它接受一个Consumer<String>,基本上只是使用一个回调Consumer<String>参数的Consumer<UUID>实现调用Gateway#process

理想情况下,您只需调用Interactor#process并验证对您提供的Consumer<String>的调用即可。

你的问题是。

Gateway的实现者触发Consumer<UUID> (以及随后的Consumer<String>)。所以你需要注入一个Gateway的实现来做这件事。

解决方案是...

按照您提供的答案(即使用伪对象而不是Mock),除非在您的生产代码中有一个可以轻松使用的Gateway的真实实现(但我假设您已经在这样做了)。

你能用Mockito做到吗?当然,您可以在模拟对象的方法参数上调用方法,如下面的答案所示:https://stackoverflow.com/a/16819818/775138 -但是如果您可以在一行中提供足够的Gateway实现,为什么还要这样做:

代码语言:javascript
复制
Gateway gw = (message, consumer) -> consumer.accept(uuid);

其中uuid是您之前构造的UUID实例。因此,不需要为此声明一个静态内部类。

然而..。

您的断言有一个重要的问题:如果Interactor什么也不做,而不是调用Gateway,那么您提供的Consumer<String> (包含断言)将不会被触发,因此您的测试将通过!只需将该值赋给测试类的成员变量,并在lambda外部进行断言。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50199260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档