3

I have broken my code down into separate functions for unit testing. I am trying to pick up Pytest testing framework and so far only know the basics.

I don't actually want to send a request to the internet -- this would be a fruitless test since I'd only be testing the urllib library anyway. I do, however, want to test how the response is handled.

I have this function to make the request

def request_url(url):
    return request.urlopen(url)

And then I am checking the content type:

def get_document_type(req):
    """ checks if document is html or plain text """
    doc_type = req.info().get_content_type()
    if doc_type == "text/html":
        return "html"
    elif doc_type == "text/plain":
        return "txt"
    else: 
        return error_message["unsupported_document_type"]

Then I will need to test and I will need to mock each outcome. If this was Node.js I could use something like rewire or a sinon stub.

def get_content(req):
    doc_type_response = get_document_type(req)
    if doc_type_response == "html":
        # handle html content
    elif get_type_response == "txt":
        # handle plain text
    else:
        return doc_type_response

This unit test works but I don't want to make the real call.

def test_request_url():
    url = request_url(url_to_try).info().get_content_type() 
    assert url == "text/plain"

Does anybody know the best way to do this please?

SarahJessica
  • 473
  • 1
  • 7
  • 18
  • Not sure if I completely understood your problem, but isn't the mock python library used for these purposes? [Read more here](https://bhch.github.io/posts/2017/09/python-testing-how-to-mock-requests-during-tests/) – kingmakerking Jan 08 '20 at 10:37
  • Is it? I really don't know it. Perhaps you could show an example implementation? – SarahJessica Jan 08 '20 at 10:42
  • The link which I shared has very clear example. – kingmakerking Jan 08 '20 at 10:44
  • The example is using unittest. What I am trying to implement is more a bit more complicated than just mocking a status code. I have tried and get "ModuleNotFoundError: No module named 'mock'" so is it only available in unittest (which I don't know either)? – SarahJessica Jan 08 '20 at 11:41

1 Answers1

3

There is a package requests-mock https://pypi.org/project/requests-mock/ which can be used for mocking API calls but for requests library. This is an example with headers/text

import unittest
import requests_mock
import requests

class TestImplementations(unittest.TestCase):

    @requests_mock.mock()
    def test_get_project(self, mock_for_requests):
        API_URL = "https://someapi.com"

        #mocking your request(s)
        expected_headers = {'Content-Type': 'text/plain'}
        expected = 'some_text'
        mock_for_requests.get(API_URL + "/someendpoint", headers=expected_headers, text=expected)

        #running your code with requests
        response = requests.get(API_URL + "/someendpoint")

        #comparing output
        self.assertEqual(response.headers, expected_headers)
        self.assertEqual(response.text, expected)
Dmytro
  • 31
  • 1
  • Hi Dmytro, thanks for this. I have tried implementing this with Pytest but I get "fixture 'mock_for_requests' not found". I think it needs to be defined outside of the test then passed in. The documentation here https://requests-mock.readthedocs.io/en/latest/pytest.html is beyond unhelpful, unfortunately. – SarahJessica Jan 09 '20 at 16:52
  • Hi. What python version you are using? requests_mock requires at least 3.6. I have successfully run this code using pycharm and python 3.8 – Dmytro Jan 10 '20 at 09:02
  • I'm using 3.8. I think the problem is that I'm using Pytest not Unittest for testing. – SarahJessica Jan 10 '20 at 09:50
  • This is working fine with pytest as well `python3.8 -m pytest script.py` – Dmytro Jan 10 '20 at 17:15
  • 1
    The problem with that snippet is you are mixing pytest and unittest. They work but pytest doesn't do fixtures the same way unittest does. There's no minimum python version for requests-mock, instead you need to call the fixture as a proper pytest fixture. see https://stackoverflow.com/a/52065289/544047 for background. – jamielennox Feb 05 '20 at 02:33