Reputation: 1750
I have the following class:
class Toto():
@staticmethod
def factory():
return Toto("Toto")
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
@staticmethod
def method_to_test():
# do stuff
toto_object = Toto.factory()
# do stuff with toto_object
toto_object.get_name()
I want to mock
the factory
method of Toto
so when it's called, it returns a mock of Toto
.
The following test should then pass:
from junit.toto import Toto
def test_toto_method_to_test(mocked):
mocked_toto = mocker.patch("junit.toto.Toto")
mocked_toto.get_name.return_value = "Tata"
mocked_toto_factory = mocker.patch(__name__ + ".Toto.factory")
mocked_toto_factory.return_value = mocked_junit_xml_generator
Toto.method_to_test()
mocked_toto.get_name.assert_called()
#mocked_toto and mock in the tested method are not the same -> FAIL
Currently, I fail to properly mock the factory method.
Upvotes: 0
Views: 1330
Reputation: 16855
The problem is that in your test, you don't use the mocked instance of Toto
, which resides in the Toto
module, but the one imported in the test itself (from ... import Toto
). To fix this, there are 2 possibilities: use the mocked object, or mock the reference in the test itself.
To use the mocked object, you shall import the module containing the object to be mocked:
import junit
def test_toto_mock(mocker):
mocked_toto = mocker.patch("junit.toto.Toto")
mocked_toto.get_name.return_value = "Tata"
assert mocked_toto.get_name() == "Tata"
mocked_toto.factory.return_value = mocked_toto
# use the same reference that you have mocked
assert junit.toto.Toto.factory().get_name() == "Tata"
If you import the object using from ... import
, you have to patch the reference in the test module instead, with __name__
containing the name of the current module:
from junit.toto import ToTo
def test_toto_mock(mocker):
# mock the reference in the test itself
mocked_toto = mocker.patch(__name__ + ".Toto")
mocked_toto.get_name.return_value = "Tata"
assert mocked_toto.get_name() == "Tata"
mocked_toto.factory.return_value = mocked_toto
# use the local reference of ToTo
assert Toto.factory().get_name() == "Tata"
If for some reason you need to mock both instances, as mentioned in the comments, you can also do this:
import junit
from junit.toto import ToTo
def test_toto_mock(mocker):
mocked_toto = mocker.patch(__name__ + ".Toto")
# replace the object in the other module with the same mock
mocker.patch("junit.toto.Toto", mocked_toto)
mocked_toto.get_name.return_value = "Tata"
assert mocked_toto.get_name() == "Tata"
mocked_toto.factory.return_value = mocked_toto
assert Toto.factory().get_name() == "Tata"
assert junit.toto.Toto.factory().get_name() == "Tata"
Please read where to patch for more information.
Upvotes: 1