我是测试驱动开发的新手,我刚刚开始学习SOLID原理,所以我希望有人可以帮助我。在开发TDD范例中的单元测试和方法的背景下,我在理解单一责任原则方面遇到了一些概念上的困难。例如,假设我想开发一种从数据库中删除项目的方法 - 在我的代码看起来如下之前......
我从定义测试用例开始:
"Delete_Item_ReturnsTrue": function() {
//Setup
var ItemToDelete = "NameOfSomeItem";
//Action
var BooleanResult = Delete( ItemToDelete );
//Assert
if ( BooleanResult === true ) {
return true;
} else {
console.log("Test: Delete_Item_ReturnsTrue() - Failed.");
return false;
}
}
我运行测试以确保失败,然后我开发了这种方法......
function Delete( ItemToDelete ) {
var Database = ConnectToDatabase();
var Query = BuildQuery( ItemToDelete );
var QueryResult = Database.Query( Query );
if ( QueryResult.error !== true ) {
//if there's no error then...
return true;
} else {
return false;
}
}
如果我正确理解单一责任原则,我最初编写的方法有责任删除项目,如果没有错误则返回true。因此,如果我遵循SOLID范例,原始方法应该重构为类似......
function Delete( WhatToDelete, WhereToDeleteItFrom ) {
WhereToDeleteItFrom.delete( WhatToDelete );
}
如此设计,将我的方法从布尔函数改为void函数,所以现在我无法以与测试旧方法相同的方式测试新方法。
我想我可以测试抛出的异常,但是它不会使它成为集成测试而不是单元测试,因为方法中没有抛出实际的异常?
我是否设计并实现了一个额外的功能,用于检查数据库以便在我的单元测试中使用?
我是不是因为它无效而不测试它?这在TDD中究竟有用吗?
我是否会传入模拟存储库,然后在状态发生变化后将其返回?是不是只是将我带回了原点?
我是否传入对模拟存储库的引用,然后在方法完成后对存储库进行测试?虽然不会被视为副作用吗?
答案 0 :(得分:2)
所以单一责任原则说:当我需要改变一个功能时,它们应该是一个原因。
让我们来看看你的功能:
function Delete( ItemToDelete ) {
var Database = ConnectToDatabase();
var Query = BuildQuery( ItemToDelete );
var QueryResult = Database.Query( Query );
if ( QueryResult.error !== true ) {
//if there's no error then...
return true;
} else {
return false;
}
}
所以在第一眼看来,你的功能看起来不错。某些地方的命名有点令人困惑。函数应该以小写字母开头。例如" connectToDatabase()"。 connectToDatabase返回一个Object有点令人惊讶。
名称BuildQuery似乎是错误的,因为BuildQuery(myItem)返回一个删除内容的查询。
但我永远不会有这么长的复杂功能只有一个测试用例。
您需要编写更多测试用例。 对于第一个测试用例,您可以编写如下函数:
function Delete( ItemToDelete) {
return true
}
下一个测试用例可能是"使用项目ID"调用buildDeleteQuery函数。那时你需要考虑如何调用你的数据库。如果你有一个dbObject,那就可以模拟那个Object。
function Delete( ItemToDelete ) {
buildDeleteQuery( ItemToDelete.id )
return true
}
现在越来越多的测试用例。请记住,还会有buildDeleteQuery的测试用例。但是对于外部函数,你可以模拟buildDeleteQuery。
现在回答你的一些问题:
但最重要的是:继续练习!当您从TDD开始时需要一些时间。一个好的和有趣的资源是:Uncle Bobs Bowling Kata只需从网站下载幻灯片,看看tdd是如何逐步完成的。