RocketMQ是我们常用的消息中间件,在运行单元测试时,我们可能不需要真正发送消息(除非是为了测试发送消息),也不想因为连结不上RocketMQ的Broker,NameServer而影响单元测试运行。
那我们该如何Mock RocketMQ消息生产者呢?
请看例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//RocketMQ消息生产者 Mock
public
class
RocetMQProducerMockingTest {
// 把RocketMQ的生产者mock
@BeforeClass
public
static
void
mockRocketMQ() {
new
RocketMQProducerMockUp();
}
@Test
public
void
testSendRocketMQMessage()
throws
Exception {
DefaultMQProducer producer =
new
DefaultMQProducer(
"test_producer"
);
producer.setNamesrvAddr(
"192.168.0.2:9876;192.168.0.3:9876"
);
producer.start();
for
(
int
i =
0
; i <
20
; i++) {
Message msg =
new
Message(
"testtopic"
,
"TagA"
, (
"Hello "
+ i).getBytes());
// 因为mq生产者已经mock,所以消息并不会真正的发送,即使nameServer连不上,也不影响单元测试的运行
SendResult result = producer.send(msg);
Assert.isTrue(result.getSendStatus() == SendStatus.SEND_OK);
Assert.isTrue(result.getMsgId() !=
null
);
}
producer.shutdown();
}
}
|
最关键的类是RocketMQProducerMockUp,这个类改变了生产者默认实现。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
//MQ消息发送者 的MockUp(伪类)
public
class
RocketMQProducerMockUp
extends
MockUp<DefaultMQProducer> {
@Mock
void
init()
throws
MQClientException {
// 构造函数也什么都不做
}
@Mock
void
start()
throws
MQClientException {
// 启动,什么都不做
}
@Mock
void
shutdown() {
// 关闭,也什么都不做
}
@Mock
List<MessageQueue> fetchPublishMessageQueues(
final
String topic)
throws
MQClientException {
// 欺骗调用方,返回不存在的消息队列,因为消息并不会真正发送嘛
List<MessageQueue> queues =
new
ArrayList<MessageQueue>();
MessageQueue q =
new
MessageQueue();
q.setBrokerName(
"testbrokername"
);
q.setQueueId(
1
);
q.setTopic(
"testtopic"
);
queues.add(q);
return
queues;
}
// 下面是对各个send方法的mock,都返回消息成功结果
@Mock
SendResult send(
final
Message msg)
throws
MQClientException, RemotingException, MQBrokerException, InterruptedException {
return
newSuccessSendResult();
}
@Mock
SendResult send(
final
Message msg,
final
long
timeout)
throws
MQClientException, RemotingException, MQBrokerException, InterruptedException {
return
newSuccessSendResult();
}
@Mock
void
send(
final
Message msg,
final
SendCallback sendCallback)
throws
MQClientException, RemotingException, InterruptedException {
sendCallback.onSuccess(
this
.newSuccessSendResult());
}
@Mock
void
send(
final
Message msg,
final
SendCallback sendCallback,
final
long
timeout)
throws
MQClientException, RemotingException, InterruptedException {
sendCallback.onSuccess(
this
.newSuccessSendResult());
}
@Mock
void
sendOneway(
final
Message msg)
throws
MQClientException, RemotingException, InterruptedException {
}
@Mock
SendResult send(
final
Message msg,
final
MessageQueue mq)
throws
MQClientException, RemotingException, MQBrokerException, InterruptedException {
return
newSuccessSendResult();
}
@Mock
SendResult send(
final
Message msg,
final
MessageQueue mq,
final
long
timeout)
throws
MQClientException, RemotingException, MQBrokerException, InterruptedException {
return
newSuccessSendResult();
}
@Mock
void
send(
final
Message msg,
final
MessageQueue mq,
final
SendCallback sendCallback)
throws
MQClientException, RemotingException, InterruptedException {
sendCallback.onSuccess(
this
.newSuccessSendResult());
}
@Mock
void
send(
final
Message msg,
final
MessageQueue mq,
final
SendCallback sendCallback,
long
timeout)
throws
MQClientException, RemotingException, InterruptedException {
sendCallback.onSuccess(
this
.newSuccessSendResult());
}
@Mock
void
sendOneway(
final
Message msg,
final
MessageQueue mq)
throws
MQClientException, RemotingException, InterruptedException {
}
@Mock
SendResult send(
final
Message msg,
final
MessageQueueSelector selector,
final
Object arg)
throws
MQClientException, RemotingException, MQBrokerException, InterruptedException {
return
newSuccessSendResult();
}
@Mock
SendResult send(
final
Message msg,
final
MessageQueueSelector selector,
final
Object arg,
final
long
timeout)
throws
MQClientException, RemotingException, MQBrokerException, InterruptedException {
return
newSuccessSendResult();
}
@Mock
void
send(
final
Message msg,
final
MessageQueueSelector selector,
final
Object arg,
final
SendCallback sendCallback)
throws
MQClientException, RemotingException, InterruptedException {
sendCallback.onSuccess(
this
.newSuccessSendResult());
}
@Mock
void
send(
final
Message msg,
final
MessageQueueSelector selector,
final
Object arg,
final
SendCallback sendCallback,
final
long
timeout)
throws
MQClientException, RemotingException, InterruptedException {
sendCallback.onSuccess(
this
.newSuccessSendResult());
}
@Mock
void
sendOneway(
final
Message msg,
final
MessageQueueSelector selector,
final
Object arg)
throws
MQClientException, RemotingException, InterruptedException {
}
@Mock
TransactionSendResult sendMessageInTransaction(
final
Message msg,
final
LocalTransactionExecuter tranExecuter,
final
Object arg)
throws
MQClientException {
return
newTransactionSendResult();
}
private
TransactionSendResult newTransactionSendResult() {
TransactionSendResult success =
new
TransactionSendResult();
success.setSendStatus(SendStatus.SEND_OK);
success.setMsgId(UUID.randomUUID().toString());
MessageQueue q =
new
MessageQueue();
q.setBrokerName(
"testbrokername"
);
q.setQueueId(
1
);
q.setTopic(
"testtopic"
);
success.setMessageQueue(q);
success.setLocalTransactionState(LocalTransactionState.COMMIT_MESSAGE);
return
success;
}
private
SendResult newSuccessSendResult() {
SendResult success =
new
SendResult();
success.setSendStatus(SendStatus.SEND_OK);
success.setMsgId(UUID.randomUUID().toString());
MessageQueue q =
new
MessageQueue();
q.setBrokerName(
"testbrokername"
);
q.setQueueId(
1
);
q.setTopic(
"testtopic"
);
success.setMessageQueue(q);
return
success;
}
}
|