如何创建Single.just(Void)

Min*_*aze 5 junit unit-testing java-8 vert.x rx-java

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

when(mongoClient.rxUpdate(anyString(), any(JsonObject.class), any(JsonObject.class)))
.thenReturn(Single.just(Void))
Run Code Online (Sandbox Code Playgroud)

现在Single.just(Void)不起作用,正确的方法是什么?


-更新-

所以我正在编写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);
}
Run Code Online (Sandbox Code Playgroud)

因为的返回类型mongoClient.rxUpdateSingle<Void>,所以我无法模拟该部分。

现在,我已经解决的解决方法是:

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

但这只是做事的拙劣方式,我想知道如何才能准确地创建 Single<Void>

Att*_*ila 2

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

但是,如果您坚持这个并且确实需要模拟它(无论出于何种原因),那么肯定有方法来创建实例Single<Void>,例如您可以使用 Single 类的 create 方法:

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.
);
Run Code Online (Sandbox Code Playgroud)

请注意:您将无法实际发出单个项目,因为 Void 无法在没有反射的情况下实例化。

在某些情况下最终可能起作用的一个技巧是省略泛型类型参数并发出一个对象,但这很容易导致 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)
);
Run Code Online (Sandbox Code Playgroud)

当然,您也可以使用反射(正如 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"
);
Run Code Online (Sandbox Code Playgroud)