Python patch mock appears to be called, but assert fails

PfunnyGuy picture PfunnyGuy · Mar 17, 2016 · Viewed 7.4k times · Source

I'm using Python 2.6.6

What I'm trying to do is replace the creation of an object with a Mock, to make sure that the correct calls are made. Should be straightforward.

My Module:

import dir.SubModule

class Cls( object ):
    def Start( self ):
        self.__obj = dir.SubModule.SubCls()
        self.__obj.foo()

My Test:

import MyModule
import unittest
from mock import Mock, MagicMock, patch

class MyTest( unittest.TestCase ):
    def setUp( self ):
        self.uut = MyModule.Cls()

    def test_one( self ):
        with patch( 'dir.SubModule.SubCls', spec=True ) as mockObj:
            print "mock calls before"
            print mockObj.mock_calls
            self.uut.Start()

            print "called: "      + str( mockObj.called )
            print "foo called: " + str( mockObj.foo.called )
            print "call_count: "  + str( mockObj.call_count )
            print "call_args: "   + str( mockObj.call_args )
            print "args_list: "   + str( mockObj.call_args_list )
            print "mock calls:\n" + str( mockObj.mock_calls )
            print "method calls:\n " + str( mockObj.method_calls )

The output is:

mock calls before:
[]
called: True
foo called: False
call_count: 1
call_args: call()
args_list: [call()]
mock calls:
[call(), call().foo()]
method calls:
[]

Yet the test fails:

AssertionError: Expected call: foo()
Not called

I don't get how the mock can report that the calls were made, but I can't assert that they were called. What am I missing?

EDIT: After adding in reporting of all the metrics, it seems there is something fundamental that I'm misunderstanding about python mocks. If foo() is in the calls list, then why is the call count only 1, and why does foo.called report 'False'?

Answer

user2357112 supports Monica picture user2357112 supports Monica · Mar 17, 2016

mockObj.foo is never called in this test. self.uut.Start() calls mockObj, creating a new mock, and then calls that mock's foo method. If you want to assert that this call happened, you will need to access the correct object:

mockObj.return_value.foo.assert_called_with()