Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用Unity处理IDisposable存储库?_C#_Unit Testing - Fatal编程技术网

C# 如何使用Unity处理IDisposable存储库?

C# 如何使用Unity处理IDisposable存储库?,c#,unit-testing,C#,Unit Testing,我有一份工作,其中我有一个IDisposable数据库上下文。我想在不插入数据库的情况下对这项工作进行单元测试。我有什么选择可以这样做 我使用的是微软的默认伪造程序集 我的工作: public void Work() { do { //code here using (var repository = new Repository<User>()) { rep

我有一份工作,其中我有一个IDisposable数据库上下文。我想在不插入数据库的情况下对这项工作进行单元测试。我有什么选择可以这样做

我使用的是微软的默认伪造程序集

我的工作:

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我假设您最初是在重新创建连接,以避免长时间保持连接?