soarjay
soarjay

Reputation: 651

Python3 Unittest Mocking Requests Module

I am comfortable using dependancy injection with Java's Mockito library, but have little experience using Python3's unittest.mock module. I am trying to assert that the Request instance's prepare method gets called. However the test fails on the assertion self.assertTrue(mock_request.prepare.called). Can someone please advise me on how to get this test passing?

import requests

import unittest
from unittest import mock

class Engine(object):

    def get(self, **kwargs):

        session = requests.Session()
        req = requests.Request('GET', 'http://www.google.com', params=kwargs).prepare()
        response = session.send(req, timeout=1)


class TestEngine(unittest.TestCase):

    @mock.patch('requests.Session')
    @mock.patch('requests.Request')
    def test_get(self, mock_request, mock_session):

        e = Engine()
        e.get()

        self.assertTrue(mock_request.called)
        self.assertTrue(mock_request.prepare.called)

if __name__ == '__main__':
    unittest.main()        

Upvotes: 1

Views: 970

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124388

Your code never accesses prepare on Request directly. The method is accessed on the return value of a call to Request(), so test for that instead by using the Mock.return_value attribute:

self.assertTrue(mock_request.return_value.prepare.called)

When debugging mock issues, I find it helpful to print out the Mock.mock_calls attribute for the top-level mock object; for your test printing mock_request.mock_calls produces:

[call('GET', 'http://www.google.com', params={}), call().prepare()]

showing that call().prepare() was indeed accessed (and the result of a call() is usually accessible via the Mock.return_value attribute, as shown above).

Upvotes: 4

Related Questions