【问题标题】:Call external stub from grpc test class从 grpc 测试类调用外部存根
【发布时间】:2020-04-21 05:31:09
【问题描述】:

我正在尝试使用存根调用 grpc 服务(原型存在于不同的 jar 文件中)。但是,当我尝试调用该服务时,我得到是由 io.grpc.statusruntimeexception 未找到未实现的方法引起的。在主类中也可以正常工作,但在测试用例中却不行。

DeviceGroupServiceImplBase deviceService = Mockito.mock(DeviceGroupServiceImplBase.class, AdditionalAnswers.delegatesTo(new DeviceGroupServiceImplBase() { }));

public void createInProcessServerAndChannel() throws IOException {
    // Generate a unique in-process server name.
    String serverName = InProcessServerBuilder.generateName();

    // Create a server, add service, start, and register for automatic graceful
    // shutdown.
    grpcCleanup.register(
            InProcessServerBuilder.forName(serverName).directExecutor().addService(deviceService).build().start());

    // Create a client channel and register for automatic graceful shutdown.
    ManagedChannel channel = grpcCleanup
            .register(InProcessChannelBuilder.forName(serverName).directExecutor().build());

    // Create a DeviceGroupServiceClient using the in-process channel;
    groupStub = DeviceGroupServiceGrpc.newBlockingStub(channel);
}

// Test case code
When("user calls getDevice with valid deviceUUID {string}", (String deviceUUID) -> {
    DeviceUuid request = DeviceUuid.newBuilder().setDeviceUuid(deviceUUID).build();
    DeviceGroup groupData = groupStub.getDeviceGroupByDeviceUuid(request);
});

【问题讨论】:

    标签: spring-boot junit grpc-java cucumber-junit


    【解决方案1】:

    你需要实现getDeviceGroupByDeviceUuid,默认返回未实现状态。你可以验证它是否在调用ServerCall#asyncUnimplementedUnaryCall

    DeviceGroupServiceImplBase deviceService = 
      Mockito.mock(
        DeviceGroupServiceImplBase.class, 
        AdditionalAnswers.delegatesTo(
          new DeviceGroupServiceImplBase() {
            @Override
            public void getDeviceGroupByDeviceUuid(
                DeviceUuid request, StreamObserver<DeviceGroup> responseObserver) {
              // TODO: implement
            } 
          }));
    

    【讨论】:

    • 这解决了,但为什么它再次调用方法中的实际存根,我是否也需要模拟它?
    • AdditionalAnswers.delegatesTo 选项是使模拟调用成为传递对象的真实方法。如果您想在真实对象上使用验证,这将非常有用。如果这只是模拟它可以工作,除非您需要手动绑定服务。 (无论如何都应该避免模拟)
    • //实际方法public void getDevice(Device req, StreamObserver &lt;Device&gt; respObs) { //some code logic DeviceGroup deviceGroup = groupStub.getDeviceGroupByDeviceUuid(request); }//测试用例When("user calls getDevice", () -&gt; { DeviceUuid request = DeviceUuid.newBuilder().setDeviceUuid(deviceUUID).build(); groupData = mockGroupStub.getDeviceGroupByDeviceUuid(request); responseObserver = StreamRecorder.create(); // This line is calling actual stub again deviceService.getDevice(request, responseObserver); responseObserver.awaitCompletion(5, TimeUnit.SECONDS); });
    • 是 io.grpc.testing.StreamRecorder 吗?只看代码,它不应该调用存根。也许这是下一条/上一条线?它看起来确实在调用存根。如果是这样,您应该实现该方法。顺便说一句,你不应该阻止通话(最后一行)。
    • 我已经实现了上面建议的测试方式,但实际的主存根位于服务器未启动的其他 jar 文件中。理想情况下,不应该调用实际的存根对吗?
    猜你喜欢
    • 2019-02-27
    • 2011-10-08
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    相关资源
    最近更新 更多