zoukankan      html  css  js  c++  java
  • 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线程中调用,这样就减少了多线程、异步测试会遇到的问题。

  • 相关阅读:
    Oracle和SQLServer中实现跨库查询
    sqlserver中创建链接服务器
    无法从命令行或调试器启动服务,必须首先安装Windows服务(使用installutil.exe),然后用ServerExplorer、Windows服务器管理工具或NET START命令启动它
    Win8系统运行程序提示“占位程序接收到错误数据”的解决方法
    设计模式——简单工厂模式
    设计模式——单例模式
    设计模式——观察者模式
    三一集团提前批java面经
    form表单传到后端的数据乱码
    Failed to obtain the JDBC Connection + Access denied for user 'XXX'@'localhost' (using password: YES)
  • 原文地址:https://www.cnblogs.com/resentment/p/6914283.html
Copyright © 2011-2022 走看看