Mocking Method Calls In Python

configparser, methods, mocking, python, unit-testing

Solution

You can't override a function call, but you can override the function itself.

From the docs:

>>> from unittest.mock import MagicMock
>>> thing = ProductionClass()
>>> thing.method = MagicMock(return_value=3)
>>> thing.method(3, 4, 5, key='value')
3
>>> thing.method.assert_called_with(3, 4, 5, key='value')

So in your case:

openpyxl.load_workbook = MagicMock(return_value=wb)

Problem

I have been searching stack exchange and around the web for how to do this, but I cannot understand how to mock behaviors for methods. I am trying to mock openpyxl behaviors and behaviors for my custom class. Here is my attempt: ``` import unittest from unittest.mock import MagicMock import openpyxl from MyPythonFile import MyClass class TestMyClass(unittest.TestCase): def test_myclass(self): myclass = MyClass() wb = openpyxl.workbook() ws = openpyxl.worksheet() wbPath = 'wbPath' openpyxl.load_workbook(wbPath, data_only = True) = MagicMock(return_value=wb) ``` When I try the final line I get the error "can't assign to function call". Do I need to use `patch.object('openpyxl','load_workbook')`? I am used to mocking in Java with Groovy and it's pretty straightforward. *Edit: wanted to add the finalized version of the test based on the response from @alxwrd ``` import unittest from unittest.mock import MagicMock import openpyxl import configparser from MyPythonFile import MyClass class TestMyClass(unittest.TestCase): def test_myclass(self): myclass = MyClass() wb = openpyxl.workbook() ws = openpyxl.worksheet() config = configparser.ConfigParser() openpyxl.load_workbook = MagicMock(return_value=wb) wb.get_sheet_by_name = MagicMock(return_value=ws) config.sections() = MagicMock(return_value=['Section1']) config.get = MagicMock(side_effect=['Value1','Value2']) ``` Notice that config.get gives multiple returns with the side_effect parameter, so if `config.get()` is called once in the code it returns `'Value1'` and when `config.get()` is called a second time it returns `'Value2'`.

Original source

Related problems