1

I try to write the unit test for this simple function. Basically, it receives a payload from Slack then builds a message and then send this message to the user using API.

@slack_messages.on_pattern('(?i)^help$')
def handle_help_message(event, body, match):
    message = build_help_message()
    Slack(event['team_id']).send_message(body['user'], **message)

def build_help_message():
    text = "Hello"

    return {
        'text': text,
        'attachments': [
            build_basics(),
            build_controls()
        ]
    }

I wrote this test, but it looks too complex for such a simple function. How can I make my test simpler?

class TestMesssageHandlers(TestCase):
    @mock.patch('slango.slack.Slack.send_message')
    @mock.patch('slango.slack.Slack.__init__')
    @mock.patch('apps.slackapp.help.handlers.build_help_message')
    def test_handle_help_message(self, build_message_mock, init_mock,
                                 send_message_mock):
        init_mock.return_value = None
        build_message_mock.return_value = {
            'text': mock.sentinel.text,
            'attachments': mock.sentinel.attachments
        }

        event = {
            'team_id': 'TEAMID',
            'event': {
                'text': 'help',
                'user': 'U111111'
            }
        }

        handle_help_message(event, event['event'])

        init_mock.assert_called_with(event['team_id'])
        send_message_mock.assert_called_with(
            event['event']['user'], **build_message_mock.return_value)
ryche
  • 2,004
  • 2
  • 18
  • 27

1 Answers1

1

Unit-testing is for findings those bugs that can be detected in the isolated code. Your example code, however, is dominated by interactions with the Slack component. That is, if there are bugs in this piece of code, they will be related to how you call the Slack constructor and the send_message method.

You will, however, not find these bugs with mocks of the Slack class: Imagine the correct named arguments to the send_message method are not text and attachments, but txt and attach - with your mocks, you will never notice this problem, because your mocks reflect your (mis-)understanding of how the other components work.

The conclusion is, that for this kind of code unit-testing is not the right approach, but integration testing is. If you need more examples, you could also take a look at these questions, which go in a similar direction: Mock a series of interdependent calls, or Should Unit Tests test against the REST API?.

Dirk Herrmann
  • 5,550
  • 1
  • 21
  • 47