C# 如何使用Unity处理IDisposable存储库?
我有一份工作,其中我有一个IDisposable数据库上下文。我想在不插入数据库的情况下对这项工作进行单元测试。我有什么选择可以这样做 我使用的是微软的默认伪造程序集 我的工作:C# 如何使用Unity处理IDisposable存储库?,c#,unit-testing,C#,Unit Testing,我有一份工作,其中我有一个IDisposable数据库上下文。我想在不插入数据库的情况下对这项工作进行单元测试。我有什么选择可以这样做 我使用的是微软的默认伪造程序集 我的工作: public void Work() { do { //code here using (var repository = new Repository<User>()) { rep
public void Work()
{
do
{
//code here
using (var repository = new Repository<User>())
{
repository.Save(user);
}
} while (true);
}
公共作废工作()
{
做
{
//代码在这里
使用(var repository=newrepository())
{
保存(用户);
}
}虽然(正确);
}
我正在尝试测试,在测试的这一部分,它失败了,因为它实际上创建了Repository类的一个新实例
我的测试方法:
using (ShimsContext.Create())
{
Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.Constructor = (a) => { };
Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.AllInstances.SaveT0 = (a, b) =>
{
};
var service = GetService();
service.Work(); //Throws exception
}
使用(ShimsContext.Create())
{
Data.Repository.Fakes.ShimRepository.Constructor=(a)=>{};
Data.Repository.Fakes.ShimRepository.AllInstances.SaveT0=(a,b)=>
{
};
var service=GetService();
service.Work();//引发异常
}
我如何才能伪造这个保存方法?您违反了这里的规定,这使得单元测试您的服务比应该的困难得多。您还应该避免使用通用存储库,并优先使用
相反,将抽象注入到存储库的服务中,例如,IUsersRepository
,它定义了Save
方法。然后,在服务的单元测试中,您可以简单地使用IUsersRepository
的存根实现,伪造往往会显示您的代码没有正确地以实数形式跟随D,因为您是在类内创建依赖项,而不是传递它们
更好的模式是创建一个ISaveRepository
接口,该接口反过来通过一个公开的Save()
方法实现IDisposable。然后,您应该将存储库的一个实例注入到类中。这将允许您满足using语句测试,并实现一个mock,该mock定义了一个不命中数据库的.Save()
方法
public class Test
{
private readonly ISaveRepository _userRepository;
public Test(ISaveRepository userRepository)
{
_userRepository = userRepository;
}
public void Work()
{
using (_userRepository)
{
var cont = true;
do
{
_userRepository.Save(new User());
cont = false;
} while (cont);
}
}
}
public interface ISaveRepository : IDisposable
{
void Save<T>(T model);
}
public class Repository<T> : ISaveRepository
{
public void Dispose() { }
public void Save<TT>(TT model) {}
}
public class User {}
公共类测试
{
私有只读ISaveRepository\u userRepository;
公共测试(ISaveRepository用户存储库)
{
_userRepository=userRepository;
}
公共工程()
{
使用(_userRepository)
{
var cont=真;
做
{
_userRepository.Save(新用户());
cont=假;
}while(续);
}
}
}
公共接口保存:IDisposable
{
无效保存(T型);
}
公共类存储库:ISaveRepository
{
public void Dispose(){}
公共无效保存(TT模型){}
}
公共类用户{}
请参阅依赖项注入-您需要允许传入的参数工作()或至少进入服务,否则它总是会创建一个真实的参数。我不熟悉赝品,但可能它的功能不足以满足您的需要。我知道这对于像Moq()这样的库来说是微不足道的。对于Moq来说也不是微不足道的,因为他正在工作中实例化存储库的实际具体实例。使用MS Fakes或TypeMock等应该是最后的选择。如果可以,请将代码抽象到接口中,除非它确实是您无法控制的代码,在这种情况下,您应该使用伪造类型的框架。是的,我知道这违反了DIP,但问题是我必须在每个循环中处理此上下文。是的,但是处理对象如何?如果我注入一次,作业将永远与上下文的第一个实例一起运行。Disposing是抽象的实体框架实现的一个实现细节。因此,处置是在EntityFrameworkUsersRepository内完成的。存根实现是否需要处置?XML存储库是否需要dispose?web服务调用存储库是否需要dispose?等等@ggui我假设您最初是在重新创建连接,以避免长时间保持连接?