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

时间:2015-10-15 13:41:00

标签: c# unit-testing

我有一份工作,我有一个IDisposable DbContext。我想在没有进入数据库的情况下对这项工作进行单元测试。我有什么选择呢?

我正在使用微软的默认Fakes程序集。

我的工作:

public void Work()
{
    do
    {   
        //code here                
        using (var repository = new Repository<User>())
        {
            repository.Save(user);
        }

    } while (true);
}

我正在尝试测试并且在测试的这一部分中它失败了,因为它实际上创建了一个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
}

如何伪造此Save方法?

2 个答案:

答案 0 :(得分:7)

您在这里违反了DIP,使得对您的服务进行单元测试的难度远远超过应有的水平。您还应该避免使用通用存储库并支持role interfaces

相反,请将抽象注入您的存储库服务,例如: IUsersRepository定义了您的Save方法。然后在服务的单元测试中,您只需使用IUsersRepository的存根实现。

答案 1 :(得分:2)

Fakes倾向于揭示您的代码没有正确地遵循SOLID中的D,因为您在类中创建依赖项而不是传入它们。

更好的模式是创建一个ISaveRepository接口,然后使用公开的Save()方法实现IDisposable。然后,您应该将您的存储库实例注入您的类。这将允许您满足using语句测试,以及实现一个模拟,该模拟定义了一个没有命中数据库的.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 {}