【问题标题】:Unit Testing a Method That Uses a Context Manager对使用上下文管理器的方法进行单元测试
【发布时间】:2018-10-02 15:34:04
【问题描述】:

我有一个方法要进行单元测试。该方法需要一个文件路径,然后使用上下文管理器打开该文件路径以解析一个值,然后返回该值,如果它存在的话,足够简单。

@staticmethod
def read_in_target_language(file_path):
    """
    .. note:: Language code attributes/values can occur
    on either the first or the second line of bilingual.
    """
    with codecs.open(file_path, 'r', encoding='utf-8') as source:
        line_1, line_2 = next(source), next(source)
        get_line_1 = re.search(
            '(target-language=")(.+?)(")', line_1, re.IGNORECASE)
        get_line_2 = re.search(
            '(target-language=")(.+?)(")', line_2, re.IGNORECASE)
        if get_line_1 is not None:
            return get_line_1.group(2)
        else:
            return get_line_2.group(2)

出于显而易见的原因,我想避免针对外部文件进行测试,并且不希望创建临时文件。另外,在这种情况下我不能使用 StringIO 。

如何在单元测试用例中模拟 file_path 对象?最终我需要创建一个包含不同值的模拟路径。感谢您提供任何帮助。

【问题讨论】:

    标签: python-3.x unit-testing testing mocking


    【解决方案1】:

    (免责声明:我不会说 Python,所以我可能会在细节上出错)

    我建议您改为模拟 codecs。使模拟的open 方法返回一个对象,其中包含要从read 调用返回的测试数据。这可能涉及为返回值创建另一个模拟对象;我不知道 Python 中是否有一些股票类可以用于此目的。

    然后,为了实际启用测试逻辑,向read_in_target_language 添加一个参数,表示一个可以承担原始codecs 对象角色的对象,即通过参数进行依赖注入。为方便起见,我想您可以将其默认为 codecs

    我不确定 Python 的鸭子类型在静态方法和实例方法方面能走多远,但这样的内容应该可以让您大致了解:

    def read_in_target_language(file_path, opener=codecs):
        ...
        with opener.open(file_path, 'r', encoding='utf-8') as source:
    

    如果上述方法不可行,您可以添加一个间接层:

    class CodecsOpener:
        ...
        def open(self, file_path, access, encoding):
            return codecs.open(file_path, access, encoding)
    
    class MockOpener:
        ...
        def __init__(self, open_result):
            self.open_result = open_result
    
        def open(self, file_path, access, encoding):
            return self.open_result
    
    ...
    
        def read_in_target_language(file_path, opener=CodecsOpener()):
            ...
            with opener.open(file_path, 'r', encoding='utf-8') as source:
                ...
    
    ...
    
        def test():
            readable_data = ...
            opener = MockOpener(readable_data)
            result = <class>.read_in_target_language('whatever', opener)
            <check result>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多