grpc测试

测试是软件开发中重要的一步,本文介绍如何创建grpc的测试来保证代码的质量。这里都沿用之前的server和client代码

服务端测试

public class HelloWorldServerTest {
  //定义服务名字用于绑定客户端调用的服务端
  private static final String UNIQUE_SERVER_NAME = "in-process server for " + HelloWorldServerTest.class;
  //创建一个进程内的server
  private final Server inProcessServer = InProcessServerBuilder.forName(UNIQUE_SERVER_NAME).addService(new HelloServiceImpl()).directExecutor().build();
  //创建一个进程内的channel
  private final ManagedChannel inProcessChannel = InProcessChannelBuilder.forName(UNIQUE_SERVER_NAME).directExecutor().build();

  /**
   * 初始化进城内服务器
   */
  @Before
  public void setUp() throws Exception {
    inProcessServer.start();
  }

  /**
   * 使用stub调用server并验证返回结果
   */
  @Test
  public void testSimple() throws Exception {
    HelloServiceGrpc.HelloServiceBlockingStub blockingStub = HelloServiceGrpc.newBlockingStub(inProcessChannel);
    String testName = "World";
    //调用服务
    blog.proto.ProtoObj.Result reply = blockingStub.simpleHello(ProtoObj.Person.newBuilder().setMyName(testName).build());
    //验证·
    assertEquals("hello, " + testName, reply.getString());
  }
  
  /**
   * 关闭服务器和channel
   */
  @After
  public void tearDown() {
    inProcessChannel.shutdownNow();
    inProcessServer.shutdownNow();
  }
}

客户端测试

在客户端测试之前,需要对之前的客户端进行一些改动,需要将channel变为实例变量,方便注入,这里以simple服务为例:

public class HelloClient {
    private static final Logger logger = Logger.getLogger(HelloClient.class.getName());
    //提出的channel
    private final ManagedChannel channel;
    //stub
    private final HelloServiceGrpc.HelloServiceBlockingStub blockingStub;
    //在构造方法中传入channel
    public HelloClient(ManagedChannel channel){
        this.channel=channel;
        blockingStub = HelloServiceGrpc.newBlockingStub(channel);
    }

    public void simple(String name) {
        logger.info("Will try to greet " + name + " ...");
        ProtoObj.Person person = ProtoObj.Person.newBuilder().setMyName(name).build();
        try {
            ProtoObj.Result response = blockingStub.simpleHello(person);
            logger.info(response.getString());
        } catch (StatusRuntimeException e) {
            logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
            return;
        }
    }
}

之后进行测试:

public class HelloWorldClientTest {
  //spy一个服务实例
  private final HelloServiceGrpc.HelloServiceImplBase serviceImpl = spy(new HelloServiceGrpc.HelloServiceImplBase() {
  });

  private Server fakeServer;
  private HelloClient client;
  ManagedChannel channel;
  /**
   * 模拟server和channel并创建client
   */
  @Before
  public void setUp() throws Exception {
    String uniqueServerName = "fake server.java for " + getClass();
    //创建进程内服务和channel
    fakeServer = InProcessServerBuilder.forName(uniqueServerName).directExecutor().addService(serviceImpl).build().start();
    InProcessChannelBuilder channelBuilder = InProcessChannelBuilder.forName(uniqueServerName).directExecutor();
    channel=channelBuilder.build();
    //创建client
    client = new HelloClient(channel);
  }

  @Test
  public void greet_messageDeliveredToServer() {
    ArgumentCaptor< ProtoObj.Person> requestCaptor = ArgumentCaptor.forClass( ProtoObj.Person.class);
    String testName = "world";

    client.simple(testName);
    //验证服务器期望收到的参数
    verify(serviceImpl).simpleHello(requestCaptor.capture(), Matchers.<StreamObserver<ProtoObj.Result>>any());
    assertEquals(testName, requestCaptor.getValue().getMyName());
  }
  
  @After
  public void tearDown() throws Exception {
    //关闭channel和server
    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    fakeServer.shutdownNow();
  }
}

总结

在单元测试时一大麻烦的是多线程的处理,使用InProcessServerBuilder会创建进程内的调用,server和client将同步在main线程中调用,这样就减少了多线程、异步测试会遇到的问题。

转载于:https://www.cnblogs.com/resentment/p/6914283.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值