所以我正在使用SO上的许多资源学习TDD,但我似乎无法弄清楚我对在给定方法/构造函数中实例化的私有/受保护对象做了什么。可以说我有一个连接字符串。该连接字符串用于构造Sqlcommand或Sqlhelper。好吧,我想模仿那个Sqlhelper,这样当我测试其他方法时,我不必依赖来自我的数据库的结果。但我无法访问Sqlhelper。
我该如何解决这个问题?
答案 0 :(得分:3)
它通常最好(除极少数情况外)仅测试整个类的公共接口。除非你真的需要,否则尽量不要使用其中一种变通方法(例如私有对象)。在测试中访问类的私有成员一开始往往看起来很好,因为编写测试对象的代码较少,但是当事情开始改变(并且他们会)访问类的内部的任何事情都会使更改其实现变得更加困难如果大多数测试是以这种方式编写的,那么这可能会破坏项目。
在这种特殊情况下,您正在与控件之外的外部依赖项进行交互(即SqlHelper),我建议将SqlHelper对象包装在您自己的对象中,该对象实现一个ISqlHelper接口(或者一个更合理命名的接口,用于您的场景)。
e.g。
public interface ISqlHelperWrapper
{
void ExecuteQuery();
}
然后通过你正在测试的对象的构造函数注入:
public class SqlConsumer
{
private ISqlHelperWrapper _sqlHelper;
public SqlConsumer(ISqlHelperWrapper helper)
{
this._sqlHelper = helper;
}
public void QuerySomething()
{
this._sqlHelper.ExecuteQuery();
}
}
这不仅是一个更好的设计(你已经从SqlConsumer中分离出了sql实现特定的东西,并且给出了更改的理由更少)。但是您现在可以使用模拟框架模拟ISqlHelper实例,并在构造时切换实现。
鉴于上面的连接字符串场景,您可以使用connectionstring初始化sqlhelperwrapper(有更好的名称),并且您的SqlConsumer对象不需要知道它。