【问题标题】:How to unit test class with no logic?如何对没有逻辑的类进行单元测试?
【发布时间】:2015-06-22 06:19:30
【问题描述】:

我发现为算法编写单元测试很容易。比如sort(List),很容易写出这样的测试:

list = [2, 1, 4];
assert(sort(list) == [1, 2, 4]);

但我发现很难测试没有逻辑的方法,没有if 语句,只有一组调用。

关于如何对它们进行单元测试,主要有 2 个示例:

示例 1:

假设我有一个类负责将一些数据写入文件,但这些数据是由外部函数(writeHeaderToFilewriteSerializedDatawriteEndOfFile)以特定方式写入的。

数据不是直接写入文件的,所以如果数据是这样的:

{
    list: [
        "item 1",
        "item 2"
    ],
    name: "aaa"
}

这并不意味着该文件既不是该数据的纯文本版本(没有空格),也不是简单的序列化版本或文件中的加密版本。实际的文件二进制文件对我来说是未知的。我所知道的是,我可以使用这三种方法以正确的方式写作。

此文件还包含一些其他信息,这些信息并非直接来自这 3 种方法,例如特定类型的标头(同样,我不知道它将如何在文件二进制文件中表示)。

那是类:

class FileCreator {
    populateFileWithData(File file, Data data) {
        doBlockWithLock(file, {
            Header header;
            header.format = SomeFormat;
            header.version = SomeVersion;
            writeHeaderToFile(file, header);

            writeSerializedData(file, data);

            writeEndOfFile(file);
        });
    }

    // Private
    void doBlockWithLock(File file, Lambda block) {
        file.holdWritingLock();
        block();
        file.releaseWritingLock();
    }
}

示例 2:

class Controller {

    var screenOne = new ScreenOne();
    var screenTwo = new ScreenTwo();
    var screenThree = new ScreenThree();

    void reloadButtonWasClicked() {
        screenOne.reload();
        screenTwo.reload();
        screenThree.reload();
    }
}

对于这个我可以做这样的事情:

var mockScreenOne = Mock<ScreenOne>().reload.expectOneCall();
var mockScreenTwo = Mock<ScreenTwo>().reload.expectOneCall();
var mockScreenThree = Mock<ScreenThree>().reload.expectOneCall();

Controller controller = new Controller();
controller.screenOne = mockScreenOne;
controller.screenTwo = mockScreenTwo;
controller.screenThree = mockScreenThree;

controller.reloadButtonWasClicked();

mockScreenOne.verify();
mockScreenTwo.verify();
mockScreenThree.verify();

但我没有发现它有多大价值,因为我只是在断言我正在做与我在实现中所做的相同的事情。对我来说似乎是代码重复。


测试我的 2 个示例的正确方法是什么?

【问题讨论】:

  • 暂且不说最后一个例子,在第一个例子中,你是说你不知道 writeSerializedData 或其他方法会做什么?你不知道会产生什么样的 fileFileCreator,也许是因为这些方法是另一个代码库或其他东西的一部分?
  • 没错!我确实有一些想法,它是“我的”代码库,我只是没有时间来理解这一切,如果你明白我的意思的话......
  • 如果我在测试它,我会简单地测试FileCreator.populateFileWithData 是否完成而不抛出异常。在我删除我的临时测试文件之前,我还会检查目标文件是否存在(因为它应该存在)。对于第二个,我将检查它对重新加载做出适当反应的每个屏幕;它是否填写了它应该没有错误的东西。
  • @RodrigoRuiz 在这种情况下可能更有价值的是集成测试而不是单元测试。具有序列化程序实现的 FileCreator 是否生成正确的文件?单击重新加载按钮是否会在视图中产生正确的行为?但是,由于类的简单性,它们可能未经测试。它们非常简单,要么工作要么不工作。只需使用该应用程序,您可能会注意到存在的错误。
  • @thalesmello 所以基本上你不会像我的控制器那样测试没有逻辑的类?

标签: unit-testing tdd


【解决方案1】:

在第一个示例中,如果您编写了有问题的消息并且对您的测试覆盖率感到满意,则没有理由在 FileCreator 上重现该测试逻辑。您只需要测试 FileCreator populateFileWithData 方法以确保文件已写入并且锁定机制可能有效。

你是对的,你的最后一个测试是相当微不足道的。我很想省略写它。但这取决于。是否有人可能会出现并评论其中一个面板构造函数?您是否有其他可以识别此类问题的测试?

【讨论】:

  • 它们的相似之处在于它们都没有逻辑。 1)让我们假设这 3 种方法已经过测试并且不是我的。如果我无法访问反序列化功能,我将如何测试它?另外,假设我是创建反序列化函数的人,所以它是一个单独的逻辑,我不想在 populateFileWithData 方法的单元测试中复制它 2) 省略是指不测试它吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-27
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多