-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Description
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();
}
}
new DefaultMQAdminExt()
created in the method, in the test case, we cannot get its referencedefaultMQAdminExt.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