psbits
psbits

Reputation: 1897

Patch a method outside python class

I am interested in patching a method which is called by another method in one file. Example - original.py file contains -

def A():
   a = 10
   b = 5
   return a*b;

def B():
  c = A()
  return c* 10

I want to write unit test for this file , say call it test.py

import mock
import unittest

class TestOriginal(unitest.TestCase):
    def test_Original_method(self):
       with patch(''):

How can I use patch and mock modules to test original.py. I want A() to always return MagicMock() object instead of an integer.

Upvotes: 3

Views: 5643

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1125068

You simply patch out the A global in the module under test. I'd use the @patch decorator syntax here:

import mock
import unittest
import module_under_test

class TestOriginal(unitest.TestCase):
    @patch('module_under_test.A')
    def test_Original_method(self, mocked_A):
        mocked_A.return_value = 42
        result = module_under_test.B()
        mocked_A.assert_called_with()
        self.assertEqual(result, 420)

This passes in the MagicMock mock object for A() as an extra argument to the test method.

Note that we explicitly named the module here. You could also use patch.object(), just naming the attribute on the module (which are your module globals):

class TestOriginal(unitest.TestCase):
    @patch.object(module_under_test, 'A')
    def test_Original_method(self, mocked_A):
        mocked_A.return_value = 42
        result = module_under_test.B()
        mocked_A.assert_called_with()
        self.assertEqual(result, 420)

You can still use a with statement too, of course:

class TestOriginal(unitest.TestCase):
    def test_Original_method(self):
        with patch('module_under_test.A') as mocked_A:
            mocked_A.return_value = 42
            result = module_under_test.B()
            mocked_A.assert_called_with()
            self.assertEqual(result, 420)

Upvotes: 2

Related Questions