如何模拟 EntityBus.rxSend()
How to mock EntityBus.rxSend()
io.vertx.reactivex.core.eventbus.EventBus.rxSend()
方法具有以下签名:
public <T> Single<Message<T>> rxSend(String address,
Object message,
DeliveryOptions options)
模拟它的正确方法是什么,以便它 returns 一个 Single
包含一个真实的对象?问题是 Message
class 除了需要另一个 Message
对象的构造函数之外没有构造函数。
所以以下将编译:
Mockito.when(eventBus.rxSend(Mockito.isA(String.class),
Mockito.isA(JsonObject.class),
Mockito.isA(DeliveryOptions.class))).thenReturn(Single.just(new Message<Object>(null)));
但当然 Single.just(new Message<Object>(null))
不包含可以传递给 Verticle 中的下一个处理程序的真实对象。
谢谢
就像我在评论中提到的那样,我无法回答您的直接问题,但我想推荐一种不同的方法来获得您正在寻找的结果。
出于各种原因,通常不鼓励模拟您不拥有的类型。最能引起我共鸣的两个(因为我已经成为受害者)是:
- 如果模拟依赖项的实际实现发生变化,模拟的行为将不会自动显示任何前瞻性更改。
- 测试引入的模拟越多,测试承载的认知负荷就越大。有些测试需要大量模拟才能工作。
有很多关于该主题的文章,具有更详细的观点和意见。如果您有兴趣,请参考 Mockito wiki,或者 Google 左右。
考虑到所有这些,而不是模拟 EventBus
,为什么不使用实际实例并接收由框架组成的真实回复 Messages
?当然,严格来说,这更像是集成测试而不是单元测试,但更接近您想要的测试类型。
这是我在现有项目中编写的测试示例片段,其中添加了一些注释。 (该代码引用了一些带有 -"Ext" 后缀的非标准类型,但它们对于该方法并不重要)。
private EventBus eventBus;
@Before
public setUp(@NotNull TestContext context) {
eventBus = Vertx.vertx().eventBus()
}
@Test
public void ping_pong_reply_test(@NotNull TestContext context) {
final Async async = context.async();
// the following is a MessageConsumer registered
// with the EventBus for this specific test.
// the reference is retained so that it can be
// "unregistered()" upon completion of this test
// so as not to affect other tests.
final MessageConsumer<JsonObject> consumer = eventBus.consumer(Ping.class.getName(), message -> {
// here is where you would otherwise place
// your mock Message generation.
MessageExt.replyAsJsonObject(message, new Pong());
});
final Ping message = new Ping();
final DeliveryOptions options = null;
// the following uses an un-mocked EventBus to
// send an event and receive a real Message reply.
// created by the consumer above.
EventBusExt.rxSendJsonObject(eventBus, message, options).subscribe(
result ->
// result.body() is JSON that conforms to
// the Pong type
consumer.unregister();
async.complete();
},
error -> {
context.fail(error);
}
);
}
我希望这至少能激发您对问题的一些新思考。
io.vertx.reactivex.core.eventbus.EventBus.rxSend()
方法具有以下签名:
public <T> Single<Message<T>> rxSend(String address,
Object message,
DeliveryOptions options)
模拟它的正确方法是什么,以便它 returns 一个 Single
包含一个真实的对象?问题是 Message
class 除了需要另一个 Message
对象的构造函数之外没有构造函数。
所以以下将编译:
Mockito.when(eventBus.rxSend(Mockito.isA(String.class),
Mockito.isA(JsonObject.class),
Mockito.isA(DeliveryOptions.class))).thenReturn(Single.just(new Message<Object>(null)));
但当然 Single.just(new Message<Object>(null))
不包含可以传递给 Verticle 中的下一个处理程序的真实对象。
谢谢
就像我在评论中提到的那样,我无法回答您的直接问题,但我想推荐一种不同的方法来获得您正在寻找的结果。
出于各种原因,通常不鼓励模拟您不拥有的类型。最能引起我共鸣的两个(因为我已经成为受害者)是:
- 如果模拟依赖项的实际实现发生变化,模拟的行为将不会自动显示任何前瞻性更改。
- 测试引入的模拟越多,测试承载的认知负荷就越大。有些测试需要大量模拟才能工作。
有很多关于该主题的文章,具有更详细的观点和意见。如果您有兴趣,请参考 Mockito wiki,或者 Google 左右。
考虑到所有这些,而不是模拟 EventBus
,为什么不使用实际实例并接收由框架组成的真实回复 Messages
?当然,严格来说,这更像是集成测试而不是单元测试,但更接近您想要的测试类型。
这是我在现有项目中编写的测试示例片段,其中添加了一些注释。 (该代码引用了一些带有 -"Ext" 后缀的非标准类型,但它们对于该方法并不重要)。
private EventBus eventBus;
@Before
public setUp(@NotNull TestContext context) {
eventBus = Vertx.vertx().eventBus()
}
@Test
public void ping_pong_reply_test(@NotNull TestContext context) {
final Async async = context.async();
// the following is a MessageConsumer registered
// with the EventBus for this specific test.
// the reference is retained so that it can be
// "unregistered()" upon completion of this test
// so as not to affect other tests.
final MessageConsumer<JsonObject> consumer = eventBus.consumer(Ping.class.getName(), message -> {
// here is where you would otherwise place
// your mock Message generation.
MessageExt.replyAsJsonObject(message, new Pong());
});
final Ping message = new Ping();
final DeliveryOptions options = null;
// the following uses an un-mocked EventBus to
// send an event and receive a real Message reply.
// created by the consumer above.
EventBusExt.rxSendJsonObject(eventBus, message, options).subscribe(
result ->
// result.body() is JSON that conforms to
// the Pong type
consumer.unregister();
async.complete();
},
error -> {
context.fail(error);
}
);
}
我希望这至少能激发您对问题的一些新思考。