我发现编写算法单元测试很容易。例如,对于sort(List)
这个方法,我们可以很容易地编写如下的测试:
list = [2, 1, 4];
assert(sort(list) == [1, 2, 4]);
但我发现很难测试没有逻辑,没有if
语句,只有一系列调用的方法。
主要有两个例子,我希望能得到如何对它们进行单元测试的答案:
例子1:
假设我有一个负责将数据写入文件的类,但是该数据以特定方式由外部函数(writeHeaderToFile
、writeSerializedData
和writeEndOfFile
)写入。
数据不是直接按原样写入文件的,所以如果数据像这样:
{
list: [
"item 1",
"item 2"
],
name: "aaa"
}
这并不意味着该文件既不是该数据的纯文本版本(没有空格),也不会是简单的序列化或加密版本。实际的文件二进制将是我无法知晓的内容。我只知道可以使用这3种方法来正确写入。
此文件还包含一些其他信息,这些信息不直接来自这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();
但我认为这并没有太多价值,因为我只是断言我正在实现相同的事情。对我来说看起来像是重复代码。
测试我的两个示例的正确方法是什么?
FileCreator.populateFileWithData
是否完成而不抛出异常。我还会检查目标文件是否存在(因为它应该存在),然后再删除我的临时测试文件。对于第二个测试,我会检查每个屏幕是否对重新加载做出了适当的反应;它是否填写了应该填写的内容而没有错误。 - Ian Boyd