我想模拟我的 grpc 客户端,以通过抛出 new StatusRuntimeException(Status.UNAVAILABLE)
来确保它对失败具有弹性。 (这是 java.net.ConnectException: Connection refused
被抛出到 grpc 客户端时抛出的异常)。但是,生成的类是最终的,因此模拟将不起作用。
如何让 BlahServiceBlockingStub 抛出 new StatusRuntimeException(Status.UNAVAILABLE)
无需重构我的代码来创建围绕 BlahServiceBlockingStub 的包装类?
这是我尝试过的(其中 BlahServiceBlockingStub 是由 grpc 生成的):
@Test
public void test() {
BlahServiceBlockingStub blahServiceBlockingStub = mock(BlahServiceBlockingStub.class);
when(blahServiceBlockingStub.blah(any())).thenThrow(new StatusRuntimeException(Status.UNAVAILABLE));
blahServiceBlockingStub.blah(null);
}
不幸的是,我按预期得到了以下异常:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class BlahServiceGrpc$BlahServiceBlockingStub
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
at MyTestClass.test(MyTestClass.java:655)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
.
.
.
因为我尝试模拟 grpc 生成的最终类:
public static final class BlahServiceBlockingStub extends io.grpc.stub.AbstractStub<BlahServiceBlockingStub> {
private BlahServiceBlockingStub(io.grpc.Channel channel) {
super(channel);
}
最佳答案
不要模拟客户端 stub 或任何其他最终类/方法。 gRPC 团队可能会不遗余力地破坏您对此类模拟的使用,因为它们非常脆弱,可能会产生“不可能”的结果。
模拟服务,而不是客户端 stub 。当与过程中的传输相结合时,它可以进行快速、可靠的测试。这与 grpc-java hello world example 中演示的方法相同.
@Rule
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
@Test
public void test() {
// This can be a mock, but is easier here as a fake implementation
BlahServiceImplBase serviceImpl = new BlahServiceImplBase() {
@Override public void blah(Request req, StreamObserver<Response> resp) {
resp.onError(new StatusRuntimeException(Status.UNAVAILABLE));
}
};
// Note that the channel and server can be created in any order
grpcCleanup.register(InProcessServerBuilder.forName("mytest")
.directExecutor().addService(serviceImpl).build().start());
ManagedChannel chan = grpcCleanup.register(
InProcessChannelBuilder.forName("mytest").directExecutor().build();
BlahServiceBlockingStub blahServiceBlockingStub
= BlahServiceGrpc.newBlockingStub();
blahServiceBlockingStub.blah(null);
}
在进行多个测试时,您可以将服务器、 channel 和 stub 创建提升到字段或
@Before
中。 ,在个人测试之外。这样做时可以方便地使用 MutableHandlerRegistry
作为 fallbackHandlerRegistry()
在服务器上。这允许您在服务器启动后注册服务。见 route guide example有关该方法的更完整示例。
关于java - 如何使用 mockito 模拟 grpc ServiceBlockingStub 抛出 StatusRuntimeException(Status.UNAVAILABLE)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59536673/