问题
I have a class that actually connects to a service and does authentication and stuff, but all of this is well tested somewhere else in my code, I just want to mock in the following test:
Object with tedious __init__
class B(object):
def __init__(self, username, password):
con = connect_to_service() #
auth = con.authenticate(username, password)
def upload(self)
return "Uploaded"
class A(object):
def send():
b = B('user', 'pass')
b.upload()
tests.py
# Now, I want here to test A, and since it uses B, I need to mock it, but I can't get it to work.
def test_A():
# Here I need to mock B and B.upload, I tried this:
a = A()
b = Mock()
b.upload.return_value='Hi'
a.send()
But this test is failling because it reached auth() on B.init, which I want to be a Mock model.
回答1:
I think that is a typical use case for mock.patch
. Take care that patch
decorator need the full path of the module where the main module become __main__
from mock import patch, Mock
from abmodule import A, B #Where A and B are
@patch("abmodule.B")
def test_A(bmock):
# Set B costructor to return a Mock object
bmock.return_value = Mock()
bmock.upload.return_value='Hi'
a = A()
a.send()
#Check if upload was called!
bmock.return_value.upload.assert_called_with()
After that you could use use again the original B
in the other part of the code: the patched version live just in scope of the function.
回答2:
You need to patch the actual class with the mocked B. py.test provides the monkeypatch
fixture for this:
import unittest.mock
import mut # module under test, where A and B are defined.
def test_A(monkeypatch):
b = unitest.mock.Mock()
b.upload.return_value = 'Hi'
monkeypatch.setattr(mut, 'B', b)
a = mut.A()
a.send()
来源:https://stackoverflow.com/questions/26374539/mock-a-class-with-tedious-init