Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magic mock assert_called_once vs assert_called_once_with weird behaviour

I am noticing a weird behavior with assert_called_once and assert_called_once_with in python. This is my real simple test:

File module/a.py

from .b import B

class A(object):
    def __init__(self):
        self.b = B("hi")

    def call_b_hello(self):
        print(self.b.hello())

File module/b.py

class B(object):
    def __init__(self, string):
        print("created B")
        self.string = string;

    def hello(self):
        return self.string

These are my tests:

import unittest
from mock import patch
from module.a import A    

class MCVETests(unittest.TestCase):
    @patch('module.a.B')   
    def testAcallBwithMockPassCorrect(self, b1):
        a = A()
        b1.assert_called_once_with("hi")
        a.call_b_hello()
        a.b.hello.assert_called_once()

    @patch('module.a.B')
    def testAcallBwithMockPassCorrectWith(self, b1):
        a = A()
        b1.assert_called_once_with("hi")
        a.call_b_hello()
        a.b.hello.assert_called_once_with()

    @patch('module.a.B')
    def testAcallBwithMockFailCorrectWith(self, b1):
        a = A()
        b1.assert_called_once_with("hi")
        a.b.hello.assert_called_once_with()

    @patch('module.a.B')
    def testAcallBwithMockPassWrong(self, b1):
        a = A()
        b1.assert_called_once_with("hi")
        a.b.hello.assert_called_once()

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

My problem as stated in the name of the function is:

  • Test 1 passes correctly
  • Test 2 passes correctly
  • Test 3 fails correctly (I've removed the call to b)
  • Test 4 passes I am not sure why.

Am I doing something wrong? I am not sure but reading the documentation docs python:

assert_called_once(*args, **kwargs)

Assert that the mock was called exactly once.

like image 985
asgarro Avatar asked Feb 17 '17 12:02

asgarro


People also ask

What is the difference between mock and MagicMock?

With Mock you can mock magic methods but you have to define them. MagicMock has "default implementations of most of the magic methods.". If you don't need to test any magic methods, Mock is adequate and doesn't bring a lot of extraneous things into your tests.

What is Assert_called_once_with?

assert_called_once_with() is used to check if the method is called with a particular set of arguments.

What is MagicMock?

MagicMock. MagicMock objects provide a simple mocking interface that allows you to set the return value or other behavior of the function or object creation call that you patched. This allows you to fully define the behavior of the call and avoid creating real objects, which can be onerous.

What does mock patch do?

patch() unittest. mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.


1 Answers

This is old, but for others landing here...

For python < 3.6, assert_called_once isn't a thing and so you're actually making a mocked function call which doesn't error

Please see: http://engineroom.trackmaven.com/blog/mocking-mistakes/

You can check the call count instead.

like image 164
Curt Avatar answered Oct 17 '22 09:10

Curt