1

I've tried to write some unit tests for a REST Client in Python. I have trouble with mocking the response from the server. Specifically, I want a GET query return a pre-prepared JSON string without connecting to the server. As I learned the way to do that in Python is to use unittest.mock or pytest-mock. My project structure is as such:

workspace/__init__.py
workspace/module/__init__.py
workspace/module/connector.py
workspace/tests/__init__.py
workspace/tests/test_connector.py

I put the test code in test_connector.py. I've tried to use unittest.mock.patch in this way:

@patch()
test_get_container_list(mocker):
    (....)

as well as pytest-mock:

mocker.patch('module.connector.Connector.get_container_list.requests.sessions.get')
mocker.return_value.ok = True
mocker.return_value.json.return_value = container_list

I've been stumped however by this error:

ImportError: No module named 'module.connector.Connector'; 'module.connector' is not a package

I've also tried to modify what I'm putting in path, but all I got was:

ImportError: No module named 'Connector'
ImportError: No module named 'connector.Connector'; 'connector' is not a package

I launched tests with this command:

pytest tests/

from the module directory. My imports look like this:

import configparser
import pytest
from module.connector import Connector

Environment: Ubuntu 16.04, Python 3.5.2, pytest-3.2.5, py-1.5.2, pluggy-0.4.0; plugins: mock-1.6.3, cov-2.5.1

All remaining tests work without problems, just this one with mocking does not.

My question: how do I make mocked tests work correctly? (import errors appear wheather I use pytest-mock or unittest.mock).

Community
  • 1
  • 1
sophros
  • 14,672
  • 11
  • 46
  • 75
  • Remove `workspace/__init__.py` file? Do you need `workspace` to be a package? – hoefling Dec 07 '17 at 08:42
  • `__init__.py` is not needed there but removing it did not help. – sophros Dec 07 '17 at 14:01
  • Your problem is obviously not pytest or mocking, you have problems with import resolving. If I recreate the setup you described (`workspace` dir, `module` and `tests` packages with class `Connector` in `module`, I am able to import the class in tests and patch it via `unittest.mock`, `pytest-mock` or `monkeypatch`. So this is clearly not the problem. Also, this: _I launched tests with this command: `pytest tests/` from the module directory_ can't run with the directory structure you described. – hoefling Dec 07 '17 at 15:00

3 Answers3

1

I went another route and instead of using pytest-mock I used request-mock. The approach here is to perform the HTTP requests normally with requests and mock the response of a particular URL.

import requests
import requests_mock

def test_requests():
    with requests_mock.Mocker() as mock:
        session = requests.Session()
        url = 'https://google.com/'

        mock.register_uri('GET', url, text='{"answer": "My return text"}')  # mocking the http response within this context
        resp = session.get('https://google.com/')
        assert resp.json()['answer'] == 'My return text'

Check for more info here and probably you'll want to check regarding request matching here.

Hope this gives you some inspiration for an alternative approach.

Ignacio Vergara Kausel
  • 5,521
  • 4
  • 31
  • 41
0

I think the issue might have been a problem with Pytest and importing, which basically everyone (myself included) seems to have, judging by the number of similar questions about it on here that I've come across.

This answer was particularly helpful for me.

Tim
  • 1,839
  • 10
  • 18
0

I did have the same error as you, the issue for me was that I wanted to patch like so @patch("org.services.main.EmailMultiAlternatives.get_connection"), while expecting the from django.core.mail import EmailMultiAlternatives import line at the top of the org.services.main module.

I didn't have that import (due to a mistake I made while resolving a GIT merge conflict), and got the same error as you did.

When restoring the import statement the tests ran without problem.

You seem to have the correct import statement, so this may not be an answer to your question. But anyone having this error should make sure they are importing the object they want to mock in the file where they are mocking it.

Rik Schoonbeek
  • 3,908
  • 2
  • 25
  • 43