Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test a POST method in python?

I have a method that sends a POST containing a JSON to an Elasticsearch instance. I am trying to write a unit test that verify the contents of the sent JSON, but I am not sure how to go about that. Should I create a local server in python and have it verify the contents of the POST or something else? I currently have this:

class TestAnalytics(BaseTest):

    def test_post(self):
        info = {"test1": "value1", "test2": "value2"}
        resp = requests.post(config.tool_repo_urls['es_url'], data=json.dumps(info), headers={'Content-Type': 'application/json'})
        assert_equal(resp.status_code, 200)  # verify valid response code
like image 504
Citut Avatar asked Jul 27 '18 15:07

Citut


People also ask

How does unit test work in Python?

Unit testing is a method for testing software that looks at the smallest testable pieces of code, called units, which are tested for correct operation. By doing unit testing, we can verify that each part of the code, including helper functions that may not be exposed to the user, works correctly and as intended.

What is pytest mocking?

In pytest , mocking can replace the return value of a function within a function. This is useful for testing the desired function and replacing the return value of a nested function within that desired function we are testing.


2 Answers

Creating a local server would be an overkill, what you can do is use unitest library to patch the post() method so it sends the data to your internal assertion method using patch method here is the link https://docs.python.org/3/library/unittest.mock-examples.html. You should look at section 27.6.2. Patch Decorators

Example:

class TestAnalytics(BaseTest):

    @patch('requests.post')
    def test_post(self,mock_post):
        info = {"test1": "value1", "test2": "value2"}
        resp = requests.post(config.tool_repo_urls['es_url'], data=json.dumps(info), headers={'Content-Type': 'application/json'})
        #Some checks done on mock_post object

Full working example below EDIT:

import json

from unittest import TestCase
from unittest.mock import patch

import requests


class TestAnalytics(TestCase):

    @patch('requests.post')
    def test_post(self, mock_post):
        info = {"test1": "value1", "test2": "value2"}
        resp = requests.post("www.someurl.com", data=json.dumps(info), headers={'Content-Type': 'application/json'})
        mock_post.assert_called_with("www.someurl.com", data=json.dumps(info), headers={'Content-Type': 'application/json'})


TestAnalytics().test_post()

Method assert_called_with checks if the patched method was called exactly with the parameters specified in its invocation. In this case it is True

Changing it to for example:

mock_post.assert_called_with("www.someurl.com", data=json.dumps(info))

Will give:

AssertionError: Expected call: post('www.someurl.com', data='{"test1": "value1", "test2": "value2"}')
Actual call: post('www.someurl.com', data='{"test1": "value1", "test2": "value2"}', headers={'Content-Type': 'application/json'})

You can also use the mock_post object to check indvidiual parametrs please check the link above for the full specs of what MagicMock can do

EDIT2

Recently found out about this little library for unit testing requests

https://github.com/getsentry/responses

like image 97
CodeSamurai777 Avatar answered Oct 19 '22 03:10

CodeSamurai777


If you want to verify the sent JSON you should try json.loads(), which will throw a ValueError if the input you pass can't be decoded as JSON.

like image 1
Omar Merghany Avatar answered Oct 19 '22 02:10

Omar Merghany