2

I'm trying to figure out how to create unit tests for a function, which behavior is based on a third party service.

Suppose a function like this:

def sync_check():
    delta_secs = 90
    now = datetime.datetime.now().utcnow()
    res = requests.get('<third_party_service_url>')
    alert = SlackAlert()
    last_value = res[-1]['date'] # Last element of the array is the most recent

    secs = (now - last_value).seconds

    if secs >= delta_secs:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
    else:
        alert.notify('in sync')

What's best practice to write unit test for this function? I need to test both if and else branches, but this depends on the third party service.

The first thing that come to my mind is to create a fake webserver and point to that one (changing url) but this way the codebase would include testing logic, like:

if test:
    url = <mock_web_server_url>
else:
    url = <third_party_service_url>

But this would change my code base. Moreover, unit testing would trigger slack alerts, which doesn't have to happen.

So there I should change again the codebase like:

if secs >= delta_secs:
    if test:
        logging.debug("out of sync alert sent - testing mode")
    else:
        alert.notify("out of sync. Delay: {} seconds".format(secs))
else:
    if test:
        logging.debug("in sync alert sent - testing mode")
    else:
        alert.notify('in sync')

Which I don't really like.

Am I missing any design to solve this problem?

6

The usual approach here is to create a "mock" for the third party service.

So:

  1. Create a class that wraps the third party service and provides the minimal necessary API. From this point on, all interactions with the third party service must go through that class.
  2. Then create a local class that implements that same API but returns predictable, controllable results
  3. The function (or class) under test then has, as a dependency, a member which you will set to be the real third party service wrapper in production, and the mock object when testing
  • I was going to reference Chapter 15 of Working Effectively with Legacy Code, but I think your explanation is much more clear. – JETM Mar 20 at 14:07
  • @JETM Haha, take THAT, Michael Feathers! – Pete Mar 20 at 14:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.