1

在我的问题中,作为“mockist” TDD 从业者,我是否应该在与被测方法相同的类中模拟其他方法?, Avdi回答说:“我个人认为嘲笑 self 几乎总是一种代码味道。它是在测试实现而不是行为。” 他可能是对的,但我常常无法区分实现和行为。

我有另一个示例(在 Python 样式的伪代码中)可能会导致有用的答案:

class Consumer:

    def spec_dirpath:
        client = VCS.get_connection(self.vcs_client_name)
        client.sync()
        return client.dirpath()

    def spec_filepath:
        filepath = os.path.join(spec_dirpath(), self.spec_filename)
        if not os.path.exists(filepath):
            raise ConsumerException
        return filepath

    def get_components:
        return Components.get_components_from_spec_file(self.spec_filepath())

这里的想法是 get_components 方法调用 spec_filepath 方法以获取 get_components_from_spec_file 组件类方法将从中读取组件列表的文件的路径。spec_filepath 方法依次调用spec_dirpath,它从VCS 系统同步包含spec 文件的目录并返回该目录的路径。(尽量不要在这段代码中寻找错误——毕竟它是伪代码。)

我正在寻找有关如何测试这些方法的建议...

测试 spec_dirpath 应该非常简单。我可以模拟 VCS 类并让它返回一个模拟对象并确认调用了适当的方法(并且 spec_dirpath 方法返回模拟的 dirpath 方法返回的内容)。

但是,如果我在测试 spec_filepath 时不模拟 spec_dirpath,如何避免在 spec_filepath 测试中从 spec_dirpath 代码中复制相同的测试代码?如果我在测试 get_components 时不模拟 spec_filepath,如何避免从 spec_filepathspec_dirpath 复制测试代码?

4

2 回答 2

1

通常在单元测试中,行为是指外部可观察到的行为。

使用您的示例,可观察到的行为将是您从 get 返回的组件列表。它们来自文件的事实是实现,因此我建议围绕您返回的组件列表构建您的测试,而不要模拟文件检索,因为它是类内部的,并使用设置代码提供适当的文件。

另一种方法是制作从类的依赖项加载组件的文件,例如,使其成为构造函数参数或方法参数,以允许在类外部指定文件。在这种情况下,它将是外部的,所以我会模拟它以确保您从中获得一致的行为,以确保您的班级正确使用它。

于 2008-10-21T23:13:57.650 回答
1

单元测试更适合某种形式的依赖注入。在这种情况下,因为您在代码中创建客户端,所以您在测试中创建了一个依赖项,需要某种形式的动态模拟来处理。(在这种情况下,我们将使用部分模拟来模拟创建依赖项的调用,以避免也必须测试这些依赖项)。

如果您在启动时注入依赖项(即传入客户端对象),那么您可以轻松地模拟它,并且只测试一个类不会遇到重大困难。

因此,您需要部分模拟或依赖注入解决方案来满足这些目标。

于 2008-10-22T00:07:52.487 回答