如何创建Single.just(Void)

时间:2018-02-01 05:43:33

标签: unit-testing junit java-8 rx-java vert.x

我正在为我的应用程序编写一些单元测试用例。我想模仿MongoClient update方法,但更新会返回Single<Void>

when(mongoClient.rxUpdate(anyString(), any(JsonObject.class), any(JsonObject.class)))
.thenReturn(Single.just(Void))

现在Single.just(Void)无法正常工作,这样做的正确方法是什么?

- UPDATE -

所以我正在为updateUserProfile方法编写单元测试,为此我嘲笑service。但service.updateAccount方法返回是我无法模拟的东西。

//Controller class
public void updateUserProfile(RoutingContext routingContext){
        // some code
    service.updateAccount(query, update)
            .subscribe(r -> routingContext.response().end());
}

//Service Class
public Single<Void> updateAccount(JsonObject query, JsonObject update){
    return mongoClient.rxUpdate("accounts", query, update);
}

因为mongoClient.rxUpdate的返回类型是Single<Void>,所以我无法模仿该部分。

目前我已经找到的解决方法是:

public Single<Boolean> updateAccount(JsonObject query, JsonObject update){
    return mongoClient.rxUpdate("accounts", query, update).map(_void -> true);
}

但这只是一种hacky方式,我想知道如何才能完全创建Single<Void>

1 个答案:

答案 0 :(得分:0)

具有返回Single<Void>的方法可能会引起一些担忧,因为一些用户已经在评论中表达了对此的看法。

但是如果您坚持这样做,并且确实需要对其进行模拟(无论出于何种原因),肯定有创建Single<Void>实例的方法,例如,您可以使用Single类的创建方法:

Single<Void> singleVoid = Single.create(singleSubscriber -> {});

when(test.updateAccount(any(JsonObject.class), any(JsonObject.class))).thenReturn(singleVoid);

Single<Void> result = test.updateAccount(null, null);

result.subscribe(
        aVoid -> System.out.println("incoming!") // This won't be executed.
);

请注意:由于无法在没有反射的情况下实例化Void,因此您将无法实际发射Single项。

在某些情况下最终可以使用的技巧是省略泛型类型参数,而改为发出Object,但这很容易导致ClassCastException。我不建议使用此:

Single singleObject = Single.just(new Object());

when(test.updateAccount(any(JsonObject.class), any(JsonObject.class))).thenReturn(singleObject);

Single<Void> result = test.updateAccount(null, null);

// This is going to throw an exception:
// "java.base/java.lang.Object cannot be cast to java.base/java.lang.Void"
result.subscribe(
        aVoid -> System.out.println("incoming:" + aVoid)
);

当然,您也可以使用反射(如Minato Namikaze所建议):

Constructor<Void> constructor = Void.class.getDeclaredConstructor(new Class[0]);
constructor.setAccessible(true);
Void instance = constructor.newInstance();

Single<Void> singleVoidMock = Single.just(instance);

when(test.updateAccount(any(JsonObject.class), any(JsonObject.class))).thenReturn(singleVoidMock);

Single<Void> result = test.updateAccount(null, null);

result.subscribe(
        aVoid -> System.out.println("incoming:" + aVoid) // Prints: "incoming:java.lang.Void@4fb3ee4e"
);