Why is mocking out zeep.Client not working?

Question:

I’m writing unit tests for a piece of code that uses zeep to access a SOAP API so I want to mock out zeep. In my actual code, it looks something like this:

from zeep import Client

def do_something():
    client = Client("...")

In my test, I’m doing this:

from unittest import mock

@mock.patch('zeep.Client')
def test_do_somethi(self, MockedClient):
    do_something()

The Client that the actual function is obtaining, is the actual zeep client and not my mock. I also tried:

@mock.patch('zeep.client.Client')

and the result was the same.

I also tried:

def test_do_something(self):
  with mock.patch('zeep.client.Client') as MockedClient:
     do_something()

with no difference.

Any ideas why this isn’t working?

Asked By: pupeno

||

Answers:

When mock doesn’t work, the first thing to look for is if you are patching the right name. Three common import scenarios:

(a) If you want to mock out zeep but you import like

from zeep import Client

and your tests are in the same file, you patch Client not zeep.Client.

(b) If instead you import it like

import zeep

and then use zeep.Client in SUT code, then you patch zeep.Client.

(c) If you are testing code that lies in some other module (like mymodule) and you import zeep there with

from zeep import Client # (1)

then in your test module you

import mymodule

then you patch mymodule.Client, … or mymodule.zeep.Client if you used the alternative import zeep form in (1).

Answered By: progmatico

You must patch the method/class from file you are using it. If you want to patch Client and it is imported in some_file.py you must import it from it, and not from lib (zeep.Client)

Here is an example using the official doc from Zeep.

some_lib.py

from zeep import Client

def do_something():
    wsdl = 'http://www.soapclient.com/xml/soapresponder.wsdl'
    client = zeep.Client(wsdl=wsdl)
    return client.service.Method1('Zeep', 'is cool')

test_connection.py

from some_lib import do_something
from unittest.mock import patch

@patch('some_lib.Client')
def test_do_something(mock_zeep):
    res = do_something()
    assert mock_zeep.call_count == 1


if __name__ == '__main__':
    test_soap_conn()
Answered By: Mauro Baraldi
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.