package messaging import ( "context" "errors" "testing" "github.com/Azure/go-amqp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) type amqpSenderMock struct { mock.Mock } func (m *amqpSenderMock) Send(ctx context.Context, msg *amqp.Message, opts *amqp.SendOptions) error { return m.Called(ctx, msg, opts).Error(0) } func (m *amqpSenderMock) Close(ctx context.Context) error { return m.Called(ctx).Error(0) } var _ AmqpSender = (*amqpSenderMock)(nil) func Test_AmqpSenderSession_Close(t *testing.T) { t.Run("close without errors", func(t *testing.T) { sender := &amqpSenderMock{} sender.On("Close", mock.Anything).Return(nil) session := &amqpSessionMock{} session.On("Close", mock.Anything).Return(nil) senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } err := senderSession.Close() assert.NoError(t, err) sender.AssertNumberOfCalls(t, "Close", 1) session.AssertNumberOfCalls(t, "Close", 1) }) t.Run("close with sender error", func(t *testing.T) { sender := &amqpSenderMock{} sender.On("Close", mock.Anything).Return(errors.New("sender error")) session := &amqpSessionMock{} session.On("Close", mock.Anything).Return(nil) senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } err := senderSession.Close() assert.EqualError(t, err, "sender error") sender.AssertNumberOfCalls(t, "Close", 1) session.AssertNumberOfCalls(t, "Close", 1) }) t.Run("close with session error", func(t *testing.T) { sender := &amqpSenderMock{} sender.On("Close", mock.Anything).Return(nil) session := &amqpSessionMock{} session.On("Close", mock.Anything).Return(errors.New("session error")) senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } err := senderSession.Close() assert.EqualError(t, err, "session error") sender.AssertNumberOfCalls(t, "Close", 1) session.AssertNumberOfCalls(t, "Close", 1) }) t.Run("close with sender and session error", func(t *testing.T) { sender := &amqpSenderMock{} sender.On("Close", mock.Anything).Return(errors.New("sender error")) session := &amqpSessionMock{} session.On("Close", mock.Anything).Return(errors.New("session error")) senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } err := senderSession.Close() assert.EqualError(t, err, "sender error\nsession error") sender.AssertNumberOfCalls(t, "Close", 1) session.AssertNumberOfCalls(t, "Close", 1) }) } func Test_AmqpSenderSession_Send(t *testing.T) { t.Run("invalid topic name", func(t *testing.T) { sender := &amqpSenderMock{} session := &amqpSessionMock{} senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } data := [][]byte{[]byte("data")} err := senderSession.Send("invalid", data, "application/json", map[string]interface{}{}) assert.EqualError(t, err, "topic \"invalid\" name lacks mandatory prefix \"topic://\"") }) t.Run("content type missing", func(t *testing.T) { sender := &amqpSenderMock{} session := &amqpSessionMock{} senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } data := [][]byte{[]byte("data")} err := senderSession.Send("topic://some/name", data, "", map[string]interface{}{}) assert.EqualError(t, err, "content-type is required") }) t.Run("send", func(t *testing.T) { sender := &amqpSenderMock{} sender.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(nil) session := &amqpSessionMock{} senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } data := [][]byte{[]byte("data")} applicationProperties := map[string]interface{}{} applicationProperties["key"] = "value" err := senderSession.Send("topic://some/name", data, "application/json", applicationProperties) assert.NoError(t, err) sender.AssertNumberOfCalls(t, "Send", 1) calls := sender.Calls assert.Equal(t, 1, len(calls)) ctx, isCtx := calls[0].Arguments[0].(context.Context) assert.True(t, isCtx) assert.NotNil(t, ctx) message, isMsg := calls[0].Arguments[1].(*amqp.Message) assert.True(t, isMsg) assert.True(t, message.Header.Durable) assert.Equal(t, "topic://some/name", *message.Properties.To) assert.Equal(t, "application/json", *message.Properties.ContentType) assert.Equal(t, applicationProperties, message.ApplicationProperties) assert.Equal(t, data, message.Data) senderOptions, isSenderOptions := calls[0].Arguments[2].(*amqp.SendOptions) assert.True(t, isSenderOptions) assert.Nil(t, senderOptions) }) t.Run("send fails", func(t *testing.T) { sender := &amqpSenderMock{} sender.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("send fail")) session := &amqpSessionMock{} senderSession := &AmqpSenderSession{ Sender: sender, Session: session, } data := [][]byte{[]byte("data")} applicationProperties := map[string]interface{}{} applicationProperties["key"] = "value" err := senderSession.Send("topic://some/name", data, "application/json", applicationProperties) assert.EqualError(t, err, "send fail") sender.AssertNumberOfCalls(t, "Send", 1) }) }