【问题标题】:ModuleNotFoundError when using Mock使用 Mock 时出现 ModuleNotFoundError
【发布时间】:2021-09-24 22:09:30
【问题描述】:

我对 Python 还很陌生。我正在开发一个小型 Python 项目,结构如下:

artwork_grabber/
|
|-- artwork_grabber/
|   |-- __init__.py
|   |-- helpers.py
|
|-- tests/
|   |-- __init__.py
|   |-- test_module.py
|
|-- README

__init__.py 两个文件都没有任何内容。

helpers.py文件包含几个函数,其中之一如下:

from os import path
from tinytag import TinyTag

def create_search_term(file_path_to_song):
    """
    Takes in a file path to a song and returns a phrase that will be used to search for the song's corresponding album artwork.

    :param file_path_to_song:  a file path to an .mp3 or .m4a file.
    :type file_path_to_song: `string`, required.

    :return:  an object of type string that represents the search term to be used when finding album artwork for song file passed into the function.
    :rtype:  `string`.
    """
    if str(path.isfile(file_path_to_song)):
        tag = TinyTag.get(file_path_to_song)
        album = tag.get_album()
        artist = tag.get_artist()
        term = f"{artist} {album} Album Cover"
        return term
    else:
        return False

我想使用模拟对象库为create_search_term() 编写一个测试。在test_module.py 函数中,我有以下内容:

from unittest import TestCase
from mock import patch

import unittest
from artwork_grabber.helpers import create_search_term


class UnitTests(TestCase):

    mock_song_info = {
        "album": "A Deeper Understanding",
        "artist": "The War On Drugs"
    }

    # patch where the function is USED, not where it is DEFINED
    @mock.patch('artwork_grabber.helpers.create_search_term', return_value=mock_song_info)
    def test_create_search_term(self, mock_song):
        actual_result = create_search_term(mock_song_info)
        expected_result = "A Deeper Understanding The War On Drugs Album Cover"
        self.assertEqual(actual_result, expected_result,
                         "Expected the search terms to match.")


if __name__ == "__main__":
    unittest.main()

问题是当我从终端运行python test_module.py 时(pwd 输出/path/to/artwork_grabber/tests),我收到以下错误:

Traceback (most recent call last):
  File "test_module.py", line 5, in <module>
    from artwork_grabber.artwork_grabber import create_search_term
ModuleNotFoundError: No module named 'artwork_grabber'

知道我可能缺少什么吗?我看过几个关于使用 Mock 的教程,但它们似乎没有帮助。

【问题讨论】:

  • 与问题本身无关,但仅供参考,看起来您正在模拟要测试的功能,因此使您的单元测试无用,因为您没有经历真实的功能

标签: python python-3.x mocking python-unittest


【解决方案1】:

The Module Search Path 中所述:

当导入名为spam 的模块时,解释器首先搜索具有该名称的built-in 模块。如果没有找到,它会在变量sys.path 给出的目录列表中搜索名为spam.py 的文件。 sys.path 从这些位置初始化:

  • 包含输入脚本的目录(或未指定文件时的当前目录)。
  • PYTHONPATH(目录名称列表,与 shell 变量 PATH 语法相同)。
  • ...

因此,在您的情况下,python 查找您的模块的路径是/path/to/artwork_grabber/tests,它显然不包含任何artwork_grabber/helpers.py,因为它只包含__init__.pytest_module.py。要满足上述两种方法中的任何一种,请执行以下任一操作:

  1. 转到父文件夹cd /path/to/artwork_grabber,然后执行测试python tests/test_module.py。这将满足上面的第一个,它将包括当前路径,因此包括 artwork_grabber/helpers.py 以及其中的子目录和文件。
  2. 在变量export PYTHONPATH=${PYTHONPATH}:/path/to/artwork_grabber 中定义它以满足上述第二条。

请注意,正如@MatiasCicero 所指出的,模拟 function-x 返回 y 并断言 function-x 返回 y 是没有意义的,测试的重点是测试源代码,而不是测试测试 if它正确地做了模拟。理想情况下,您应该运行实际的create_search_term 并将其传递给测试文件file_path_to_song

【讨论】:

    猜你喜欢
    • 2022-01-01
    • 2021-03-30
    • 2020-08-03
    • 2020-08-02
    • 1970-01-01
    • 2022-12-17
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多