Search code examples
javajmsjunit5

Can not read from ActiveMQBytesMessage


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.


Solution

  • 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);
        }
    }