Как импортировать собственный модуль для насмешек? (ошибка импорта: нет модуля с именем my_module!)

Я хочу unit test мой класс, который находится в другом файле с именем client_blogger.py.

Мой unit test файл находится в том же каталоге. Все мои другие модульные тесты работают, за исключением случаев, когда я пытаюсь высмеять один из моих собственных методов.

## unit_test_client_blogger.py
import mock
import json

from client_blogger import BloggerClient, requests

Class TestProperties():

    @pytest.fixture

    def blog(self):
    return BloggerClient(api_key='123', url='http://example.com')

    @mock.patch('client_blogger._jload')
    @mock.patch('client_blogger._send_request')

    def test_gets_blog_info(self, mock_send, mock_jload):
    """ Get valid blog info from API response. """

    valid_blog_info = 'some valid json api response here'
    parsed_response = json.loads(valid_blog_info)
    correct_blog_id = '7488272653173849119'
    mock_jload.return_value = valid_blog_info

    id = self.blog().get_blog_info(parsed_response)
    assert id == correct_blog_id

И вот содержимое файла client_blogger.py:

# client_blogger.py
import requests, json

class BloggerClient(object):
    """ Client interface for Blogger API. """
    def __init__(self, key, url):
         # removed some code here for brevity

    def _send_request(self, api_request):
        """ Sends an HTTP get request to Blogger API.
            Returns HTTP response in text format. """
        # snip

    def _jload(self, api_response):
        """ Accepts text API response. Returns JSON encoded response. """
        # snip

    def get_blog_info(self):
        """ Makes an API request. Returns Blog item information. """
        request = '{b}/blogs/byurl?url={u}&key={k}'.format(b=self.base, u=self.url, k=self.key)
        txt_response = self.send_request(request)
        response = self._jload(txt_response)
        return response['id']

Я хочу издеваться над вызовами метода self.send_request() и self._jload() в указанном выше методе.

Но модуль Mock жалуется: ImportError: No module named client_blogger.

Ошибка должна лежать здесь:

@mock.patch('client_blogger._jload')
@mock.patch('client_blogger._send_request')

Я пробовал много вариантов, чтобы получить mock.patch, чтобы найти мой модуль или класс. Но никто из них не работал.

Я пробовал следующее:

@mock.patch('client_blogger.BloggerClient._jload')
@mock.patch('BloggerClient._jload')
@mock.patch('._jload')

Ни одна из этих работ не работает. Любая идея, как mock.patch метод из моего собственного модуля?

(Кажется странным, потому что я могу mock.patch другие модули, просто не мои собственные: -s)

Ответ 1

Вы хотите:

@mock.patch('client_blogger.BloggerClient._jload')
@mock.patch('client_blogger.BloggerClient._send_request')
def test_gets_blog_info(self, mock_send, mock_jload):
    """ Get valid blog info from API response. """

    valid_blog_info = 'some valid json api response here'
    parsed_response = json.loads(valid_blog_info)
    correct_blog_id = '7488272653173849119'
    mock_jload.return_value = valid_blog_info

    id = self.blog().get_blog_info(parsed_response)
    assert id == correct_blog_id

Реализация BloggerClient исходит из модуля client_blogger, поэтому вам нужно запланировать client_blogger.BloggerClient. Вы перечисляете это как одну из вещей, которые вы пробовали, которые не работают, но я просто попробовал, и это работает отлично для меня. Какой у вас был вопрос, когда вы это пробовали?

Ответ 2

Для python3 формат выглядит следующим образом:

from unittest.mock import patch
@patch('client_blogger.BloggerClient._jload')
.
.
.

Документы: https://docs.python.org/3/library/unittest.mock.html#patch

Это очень, очень важно:

patch() прост в использовании. Ключ должен сделать исправление в правильном пространстве имен. Смотрите раздел где патчить.