I'm writing a junit test where I'm trying to assert the ack message:
@ExtendWith(MockitoExtension.class)
class MessageHandlerBeanTest {
//... @Mock
@InjectMocks
MessageHandlerBean messageHandlerBean;
private BytesMessage inputMsg;
private BytesMessage outputMsg;
void setMessageContent(String xml) {
try {
inputMsg.clearBody();
inputMsg.writeBytes(xml.getBytes(StandardCharsets.UTF_8)); // for some reason writeUTF() does not encode correctly
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
@BeforeEach
void setUp() {
//...
inputMsg = new ActiveMQBytesMessage();
setMessageContent(envelope);
outputMsg = new ActiveMQBytesMessage();
Mockito.when(currSession.createBytesMessage()).thenReturn(outputMsg);
}
@Test
void valid_msg_returns_ok() throws Exception {
messageHandlerBean.onMessage(inputMsg);
Assertions.assertThat(outputMsg.getBodyLength()).isNotZero();
Assertions.assertThat(outputMsg.readUTF()).isEqualTo("<xml>...<xml>");
}
}
But I end getting this exception:
javax.jms.MessageNotReadableException: Message body is write-only
at org.apache.activemq.command.ActiveMQBytesMessage.checkWriteOnlyBody(ActiveMQBytesMessage.java:819)
at org.apache.activemq.command.ActiveMQBytesMessage.initializeReading(ActiveMQBytesMessage.java:824)
at org.apache.activemq.command.ActiveMQBytesMessage.getBodyLength(ActiveMQBytesMessage.java:182)
If I insepct the outputMsg
while in debug, this is fine, I can see the body is populated and jms properties are set as well.
I have solved it by resetting the message with outputMsg.reset();
just before the assertions.
Javadoc:
Puts the message body in read-only mode and repositions the stream of bytes to the beginning.
PS: As I was already expecting, the readUTF
does not work for me either (same as for writeUTF
), so I'm just using this instead:
String getMessageContent(BytesMessage msg) {
try {
msg.reset();
int bodyLength = (int) msg.getBodyLength();
byte[] result = new byte[bodyLength];
msg.readBytes(result, bodyLength);
return new String(result, StandardCharsets.UTF_8);
} catch (JMSException e) {
throw new RuntimeException(e);
}
}