I have a question similar to the questions posted here, which also have no satisfying answer yet:
mocking a method with another reusable method with arguments in python
Using mock patch to mock an instance method
I have the following Production class and UnitTest class. In the second test case in the UnitTest class, I want to substitute the real method for the fake method, which I have defined above the Unit Test class. However, I am unable to connect the method even_numbers
in the system under test to the fake method odd_numbers
, including its input arguments. How should this substition look like? I am using Python 2.7.
import unittest
from mock import patch
class ProdClass(object):
def even_numbers(self, numbers):
print 'This is the real method'
return [n for n in numbers if n%2 == 0]
def odd_numbers(numbers):
print 'This is the mock'
return [n for n in numbers if n%2 != 0]
class MockingTestTestCase(unittest.TestCase):
def test_even_numbers_01(self):
sut = ProdClass()
result = sut.even_numbers(range(10))
expected_result = [0, 2, 4, 6, 8]
self.assertEqual(result, expected_result,
msg = '\nRetrieved: \n{0}\nExpected: \n{1}'.format(result, expected_result))
@patch('ProdClass.even_numbers')
def test_even_numbers_02(self, mock_even_numbers):
sut = ProdClass()
'''Substitute real method even_numbers with mocked method even_numbers here'''
mock_even_numbers.return_value = odd_numbers
result = sut.even_numbers(range(10))
expected_result = [1, 3, 5, 7, 9]
self.assertEqual(result, expected_result,
msg = '\nRetrieved: \n{0}\nExpected: \n{1}'.format(result, expected_result))
if __name__ == "__main__":
unittest.main()
EDIT: With the help of Martijn below, I have edited the code into this working example:
import unittest
from mock import patch
class ProdClass(object):
def even_numbers(self, numbers):
print 'This is the real method'
return [n for n in numbers if n%2 == 0]
def odd_numbers(numbers):
print 'This is the mock'
return [n for n in numbers if n%2 != 0]
class MockingTestTestCase(unittest.TestCase):
def test_even_numbers_01(self):
sut = ProdClass()
result = sut.even_numbers(range(10))
expected_result = [0, 2, 4, 6, 8]
self.assertEqual(result, expected_result,
msg = '\nRetrieved: \n{0}\nExpected: \n{1}'.format(result, expected_result))
@patch.object(ProdClass, 'even_numbers')
def test_even_numbers_02(self, mock_even_numbers):
sut = ProdClass()
'''Substitute real method even_numbers with mocked method even_numbers here'''
mock_even_numbers.side_effect = odd_numbers
result = sut.even_numbers(range(10))
expected_result = [1, 3, 5, 7, 9]
self.assertEqual(result, expected_result,
msg = '\nRetrieved: \n{0}\nExpected: \n{1}'.format(result, expected_result))
if __name__ == "__main__":
unittest.main()