Mocking assert_called_with in Python

2024/11/15 1:07:47

I'm having some trouble understanding why the following code does not pass:

test.py

import mock
import unittestfrom foo import Fooclass TestFoo(unittest.TestCase):@mock.patch('foo.Bar')def test_foo_add(self, Bar):foo = Foo()foo.add(2, 2)Bar.add.assert_called_with(2, 2)if __name__ == '__main__':unittest.main()

foo.py

from bar import Barclass Foo(object):def add(self, x, y):bar = Bar()return bar.add(x, y)

bar.py

class Bar(object):def add(self, x, y):print('b.Bar --> Adding {} + {}'.format(x, y))return x + y

In the code, Foo.add creates an instance of Bar and returns the result of Bar.add when invoked. Why does testing assert_called_with for Bar.add fail? I believe I am mocking the Bar in the correct place (I am mocking foo.Bar because that is the namespace which it is being looked up, rather than bar.Bar).

Traceback (most recent call last):File "/Users/iain/PycharmProjects/testing/venv/lib/python2.7/site-packages/mock.py", line 1201, in patchedreturn func(*args, **keywargs)File "test.py", line 12, in test_a_bfake_Bar.add.assert_called_with(2, 2)File "/Users/iain/PycharmProjects/testing/venv/lib/python2.7/site-packages/mock.py", line 831, in assert_called_withraise AssertionError('Expected call: %s\nNot called' % (expected,)) AssertionError: Expected call: add(2, 2) Not called

Answer

You are mocking the method call in the right place. However, since you are calling the method from an instance, it is a bound method, and thus receives the instance as the first argument (the self parameter), in addition to all the other arguments.

Edit: Since Bar is replaced with a Mock instance, Bar().add does not know it's a method (and hence is not bound to anything). In other words, Bar is a Mock, Bar() is a Mock, and Bar().add is also a Mock. bar.add is thus a newly created mock, called with arguments (2, 2). One way of asserting this call would be:

@mock.patch('foo.Bar')
def test_foo_add(self, Bar):foo = Foo()foo.add(2, 2)Bar.return_value.add.assert_called_with(2, 2)

Depending on how your actual code looks, you may want to instead mock the method rather than the class:

@mock.patch('foo.Bar.add')
def test_foo_add(self, bar_add):foo = Foo()foo.add(2, 2)bar_add.assert_called_with(2, 2)
https://en.xdnf.cn/q/72279.html

Related Q&A

Python select() behavior is strange

Im having some trouble understanding the behavior of select.select. Please consider the following Python program:def str_to_hex(s):def dig(n):if n > 9:return chr(65-10+n)else:return chr(48+n)r = wh…

Moving items up and down in a QListWidget?

In a QListWidget I have a set of entries. Now I want to allow the user to sort (reorder) these entries through two buttons (Up/Down).Heres part of my code:def __init__(self):QtGui.QMainWindow.__init__(…

How to resize a tiff image with multiple channels?

I have a tiff image of size 21 X 513 X 513 where (513, 513) is the height and width of the image containing 21 channels. How can I resize this image to 21 X 500 X 375?I am trying to use PILLOW to do …

Losing elements in python code while creating a dictionary from a list?

I have some headache with this python code.print "length:", len(pub) # length: 420pub_dict = dict((p.key, p) for p in pub)print "dict:", len(pub_dict) # length: 163If I understand t…

How to set Font size or Label size to fit all device

How to set kivy font size or label size so that it will fit all phone-device screen? (fit by means does not overlap with the boundary, rectangle, or even the screen)I know the Buttons and some other W…

Using tweepy to access Twitters Streaming API

Im currently having trouble getting example code for using tweepy to access Twitters Streaming API to run correctly (err...or at least how I expect it to run). Im using a recent clone of tweepy from Gi…

Jupyter notebook, how to run multiple cells simultaneously?

I defined a python function which run a bash script. Lets say the function is: calc(x,y,z). If I run this function in python with some variables,>>> calc(1,2,3)It generates a C code which simu…

How to make a slice of DataFrame and fillna in specific slice using Python Pandas?

The problem: let us take Titanic dataset from Kaggle. I have dataframe with columns "Pclass", "Sex" and "Age". I need to fill NaN in column "Age" with a median f…

Pythons difflib SequenceMatcher speed up

Im using difflib SequenceMatcher (ratio() method) to define similarity between text files. While difflib is relatively fast to compare a small set of text files e.g. 10 files of 70 kb on average compar…

create an asymmetric colormap

I am creating a colormap to map colors in a folium choropleth map, using code from here:from branca.colormap import linearcolormap = linear.RdBu.scale(df.MyValue.min(),df.MyValue.max())colormapAs you c…