10

I'm working on a client library for a popular API. Currently, all of my unit tests of said client are making actual API calls against a test account.

Here's an example:

def test_get_foo_settings(self):
    client = MyCustomClient(token, account)
    results = client.get_foo_settings()

    assert_is(type(results), list)

I'd like to stop making actual API calls against my test account.

How should I tackle this? Should I be using Mock to mock the calls to the client and response?

Also, I'm confused on the philosophy of what to test with this client library. I'm not interested in testing the actual API, but when there are different factors involved like the method being invoked, the permutations of possible return results, etc - I'm not sure what I should test and/or when it is safe to make assumptions (such as a mocked response).

Any direction and/or samples of how to use Mock in my type of scenario would be appreciated.

1
  • I just learned about an interesting module for testing called fudge, you might check that out. Commented Feb 5, 2013 at 22:00

2 Answers 2

11

I would personally do it by first creating a single interface or function call which your library uses to actually contact the service, then write a custom mock for that during tests.

For example, if the service uses HTTP and you're using Requests to contact the service:

class MyClient(…):
    def do_stuff(self):
         result = requests.get(self.service_url + "/stuff")
         return result.json()

I would first write a small wrapper around requests:

class MyClient(…):
    def _do_get(self, suffix):
         return requests.get(self.service_url + "/" + suffix).json()

    def do_stuff(self):
         return self._do_get("stuff")

Then, for tests, I would mock out the relevant functions:

 class MyClientWithMocks(MyClient):
     def _do_get(self, suffix):
          self.request_log.append(suffix)
          return self.send_result

And use it in tests like this:

def test_stuff(self):
    client = MyClientWithMocks(send_result="bar")
    assert_equal(client.do_stuff(), "bar")
    assert_contains(client.request_log, "stuff")

Additionally, it would likely be advantageous to write your tests so that you can run them both against your mock and against the real service, so that if things start failing, you can quickly figure out who's fault it is.

Sign up to request clarification or add additional context in comments.

2 Comments

This answer would benefit from some more explanation as to why you prefer this approach, as this question suggests!
Wouldn't you rather mock requests.get() and does it make more sense to have do_stuff() call _do_get() rather than return value from do_get()?
0

I'm using HTTmock and I'm pretty happy with it : https://github.com/patrys/httmock

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.