不要对数据访问层进行单元测试。为其编写集成测试。
在 DAL 中模拟依赖项不仅值得麻烦,因为它不能保证任何事情。
如果你仔细想想,DAL 依赖于 SQL 方言和数据库模式。因此,您的单元测试可能工作得很好。但是,当您运行真正的解决方案时,它仍然会失败。原因可能是您的 SQL 查询不正确,或者类属性类型之一与表列类型不匹配。
单元测试通常是为业务逻辑编写的。他们捕获的一件事是不会产生异常的错误,例如不正确的条件或计算错误。
更新
好的。因此,您的示例实际上包含业务逻辑。方法名骗了我。
您必须改变创建 DAL 类的方式。但是您不必像 Jack Hughes 建议的那样使用构造函数注入。相反,您可以使用工厂模式:
public List<CustomerObject> FetchCustomersByName(CustomerObject obj)
{
var customerDal = DalFactory.Create<CustomerDal>();
//Maybe other operations
List<CustomerObject> list = customerDal.FetchByName(obj.Name);
//Maybe other operations over list
return list;
}
这有点容易,因为现在您可以使用“全部替换”将所有 var customerDal = new CustomerDal() 更改为 var customerDal = DalFactory.Create<CustomerDal>();
在那个工厂类中你可以调用不同的实现
public class DalFactory
{
public static IDalFactory Factory { get set; }
static DalFactory()
{
Factory = new DefaultDalFactory();
}
public static T Create<T>() where T : class
{
return Factory.Create<T>();
}
}
public interface IDalFactory
{
T Create<T>() where T : class
}
public class DefaultDalFactory : IDalFactory
{
public T Create<T>() where T : class
{
return new T();
}
}
代码并不漂亮,但它以最少的重构解决了您的问题。我建议你从那开始,然后尝试改变你的编码标准,以便允许构造函数注入。
要让它在您的测试中工作,您可以使用以下实现。它使用 [ThreadStatic] 允许同时运行多个测试。
public class TestDalFactory : IDalFactory
{
[ThreadStatic]
private static Dictionary<Type, object> _instances;
public static Dictionary<Type, object> DalInstances
{
get
{
if (_instances == null)
_instances = new Dictionary<Type, Object>();
return _instances;
}
}
public static TestDalFactory Instance = new TestDalFactory();
public T Create<T>() where T : class
{
return (T)_instances[typeof(T)];
}
}
接下来在您的测试中,您可以通过执行以下操作将 DAL 工厂配置为返回模拟:
[TestClass]
public class MyBusinessTests
{
[TestInitialize]
public void Init()
{
DalFactory.Instance = TestDalFactory.Instance;
}
[TestMethod]
public void do_some_testing_in_the_business()
{
TestDalFactory.Instance.DalInstances[typeof(CustomerDal)] = new MyNewMock();
//do the testing here
}
}