如何导入自定义模块进行模拟?(导入错误:没有名为my_module的模块!)

16 投票
3 回答
19536 浏览
提问于 2025-04-21 07:55

我想对我的一个类进行单元测试,这个类在另一个文件里,文件名是 client_blogger.py

我的单元测试文件和这个类在同一个文件夹里。除了在尝试模拟我自己方法的时候,其他的单元测试都能正常工作。

## 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 模拟一个方法呢?

这让我觉得很奇怪,因为我可以模拟其他模块,就是无法模拟我自己的模块 :-s

3 个回答

-2

对于python3,格式如下:

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

文档链接:https://docs.python.org/3/library/unittest.mock.html#patch

这点非常非常重要:

patch()的使用方法很简单。关键是要在正确的命名空间中进行补丁处理。请查看关于补丁处理的位置部分。

1

在路径中,你需要把类的文件名放在对象名称之前。比如,如果我在一个叫做 Event 的类里,有一个方法叫 foo,而这个类的文件在 tools/event.py 里,那么路径应该是这样的:

patch("tools.event.Event.foo", boo)
21

你想要的是这个:

@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进行修补。你把这个列为你尝试过但不成功的事情之一,但我刚试了一下,这对我来说是可以的。你在尝试的时候遇到了什么问题呢?

撰写回答