【问题标题】:Asserting execution order in python unittest在 python unittest 中断言执行顺序
【发布时间】:2014-06-02 17:06:37
【问题描述】:

我有一个函数可以创建一个临时目录,切换到该临时目录,执行一些工作,然后切换回原始目录。我正在尝试编写一个单元测试来测试它。我在验证当前目录是否已更改为临时目录并再次更改回之前没有问题,但我在验证这些调用之间是否发生了重要的事情时遇到了问题。

我最初的想法是将函数抽象为三个子函数,以便我可以测试调用顺序。我可以用模拟替换三个子函数中的每一个来验证它们是否被调用——但是,我仍然遇到了验证顺序的问题。在模拟中我可以使用 assert_has_calls,但我应该在什么对象上调用该函数?

这是我要测试的课程:

import shutil
import os
import subprocess
import tempfile
import pkg_resources


class Converter:
    def __init__(self, encoded_file_path):
        self.encoded_file_path = encoded_file_path
        self.unencoded_file_path = None
        self.original_path = None
        self.temp_dir = None

    def change_to_temp_dir(self):
        self.original_path = os.getcwd()
        self.temp_dir = tempfile.mkdtemp()
        os.chdir(self.temp_dir)

    def change_to_original_dir(self):
        os.chdir(self.original_path)
        shutil.rmtree(self.temp_dir)

    def do_stuff(self):
        pass

    def run(self):
        self.change_to_temp_dir()
        self.do_stuff()
        self.change_to_original_dir()

这是我写测试用例的时候:

def test_converter(self, pkg_resources, tempfile, subprocess, os, shutil):
    encoded_file_path = Mock()

    converter = Converter(encoded_file_path)
    converter.change_to_temp_dir = Mock()
    converter.do_stuff= Mock()
    converter.change_to_original_dir = Mock()

    assert converter.encoded_file_path == encoded_file_path
    assert converter.unencoded_file_path is None

    converter.run()

现在我已经模拟了每个函数,我可以验证它们是否被调用,但不能以什么顺序调用。我该怎么做?

【问题讨论】:

    标签: python unit-testing mocking python-unittest


    【解决方案1】:

    一种解决方法是创建一个单独的模拟对象,为其附加方法并使用assert_has_calls() 检查调用顺序:

    converter = Converter(encoded_file_path)
    converter.change_to_temp_dir = Mock()
    converter.do_stuff = Mock()
    converter.change_to_original_dir = Mock()
    
    m = Mock()
    m.configure_mock(first=converter.change_to_temp_dir,
                     second=converter.do_stuff,
                     third=converter.change_to_original_dir)
    
    converter.run()
    m.assert_has_calls([call.first(), call.second(), call.third()])
    

    【讨论】:

    • 那不行,方法仍然绑定到Converter,对mock_stub没有任何影响。但是,它确实给了我一个想法。如果你要撤销任务怎么办?与其将转换器函数添加到 mock_stub,不如将转换器函数替换为 mock_stub 函数会怎样?
    • @SeanPrice 检查您是否在对 converter 方法进行了模拟之后实例化了 m 模拟。
    • 啊,我明白我做了什么。您的回答很好,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-11-12
    • 2013-09-16
    • 2015-02-02
    • 2019-04-19
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多