xijiu opened a new issue #3674:
URL: https://github.com/apache/rocketmq/issues/3674


   # Present Situation
   In the tools module, the test case is closed. `pom.xml` is set up like this
   
   ```
   <properties>
       <maven.test.skip>true</maven.test.skip>
   </properties>
   ```
   
   And some test cases will fail to run, and some test cases are marked as 
`@Ignore`. The **TARGET** is fix all test cases, and set `maven.test.skip = 
false`
   
   
   
   # Problem Description
   
   But how to solve it ? The key is to solve the test cases marked by 
`@Ingore`. Let's look at a current example in class 
`ProducerConnectionSubCommandTest`
   
   ```
   private static DefaultMQAdminExt defaultMQAdminExt;
   private static DefaultMQAdminExtImpl defaultMQAdminExtImpl;
   private static MQClientInstance mqClientInstance = 
MQClientManager.getInstance().getOrCreateMQClientInstance(new ClientConfig());
   private static MQClientAPIImpl mQClientAPIImpl;
   
   @BeforeClass
   public static void init() throws NoSuchFieldException, 
IllegalAccessException, InterruptedException, RemotingTimeoutException, 
MQClientException, RemotingSendRequestException, RemotingConnectException, 
MQBrokerException {
       mQClientAPIImpl = mock(MQClientAPIImpl.class);
       defaultMQAdminExt = new DefaultMQAdminExt();
       defaultMQAdminExtImpl = new DefaultMQAdminExtImpl(defaultMQAdminExt, 
1000);
   
       Field field = 
DefaultMQAdminExtImpl.class.getDeclaredField("mqClientInstance");
       field.setAccessible(true);
       ......
   
       ProducerConnection producerConnection = new ProducerConnection();
       Connection connection = new Connection();
       ......
       
       when(mQClientAPIImpl.getProducerConnectionList(anyString(), anyString(), 
anyLong())).thenReturn(producerConnection);
   }
   
   @Ignore
   @Test
   public void testExecute() throws SubCommandException {
       ProducerConnectionSubCommand cmd = new ProducerConnectionSubCommand();
       Options options = ServerUtil.buildCommandlineOptions(new Options());
       String[] subargs = new String[] {"-g default-producer-group", "-t 
unit-test"};
       final CommandLine commandLine =
           ServerUtil.parseCmdLine("mqadmin " + cmd.commandName(), subargs, 
cmd.buildCommandlineOptions(options), new PosixParser());
       cmd.execute(commandLine, options, null);
   }
   ```
   
   
   Obviously, the original author tried to proxy the method 
`MQClientAPIImpl.getProducerConnectionList` through **Mockito + reflection** 
and return the mocked data. But the code in the `ProducerConnectionSubCommand` 
class is indeed like this
   
   ```
   @Override
   public void execute(CommandLine commandLine, Options options, RPCHook 
rpcHook) throws SubCommandException {
       DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(rpcHook);
   
       
defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));
   
       try {
           defaultMQAdminExt.start();
           ......
           
       } catch (Exception e) {
           throw new SubCommandException(this.getClass().getSimpleName() + " 
command failed", e);
       } finally {
           defaultMQAdminExt.shutdown();
       }
   }
   ```
   
   1. `new DefaultMQAdminExt()` created in the method, in the test case, we 
cannot get its reference
   2. `defaultMQAdminExt.start()` Its member variables will be reassigned
   
   Without changing the code, it is difficult to solve it through **Mockito + 
reflection**
   
   # Solution
   
   Since it cannot proxy `DefaultMQAdminExt`, just mock the network response 
data directly. We can create simple netty server for **nameServer** and 
**broker** respectively. like this
   
   ```
   protected void channelRead0(ChannelHandlerContext ctx, RemotingCommand msg) 
throws Exception {
       String remark = "mock data";
       final RemotingCommand response =
               
RemotingCommand.createResponseCommand(RemotingSysResponseCode.SUCCESS, remark);
       response.setOpaque(msg.getOpaque());
       response.setBody(getBody());
   
       if (extMap != null && extMap.size() > 0) {
           response.setExtFields(extMap);
       }
       ctx.writeAndFlush(response);
   }
   ```
   
   ```
   private ServerResponseMocker startOneBroker() {
       ProducerConnection producerConnection = new ProducerConnection();
       HashSet<Connection> connectionSet = new HashSet<>();
       Connection connection = mock(Connection.class);
       connectionSet.add(connection);
       producerConnection.setConnectionSet(connectionSet);
   
       // start broker
       return ServerResponseMocker.startServer(BROKER_PORT, 
producerConnection.encode());
   }
   ```
   
   Then specify the PORT and RESPONSE DATA for each test case. The advantage of 
this is: we only need mock the netty response data, and don't care about the 
implementation details inside the method
   
   
   
   [jump to pr](https://github.com/apache/rocketmq/pull/3672)
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to