使用依赖注入和模拟对象进行单元测试而不会访问数据库

时间:2016-01-27 10:26:15

标签: unit-testing dependency-injection

我是单元测试的新手。任何人都可以向我解释如何在不打击数据库的情况下完成单元测试

我还想知道,依赖注入是否对单元测试至关重要? 如果是,请用示例代码向我解释。这对我有帮助。

我已经创建了用于登录的单元测试,它可以访问数据库。但我想为登录测试相同的情况,而不是打击数据库。 在这里,我使用 Microsoft.VisualStudio.TestTools.UnitTesting

这是我的代码,

 [TestMethod]
    public void _01_LoginUser_01_Valid()
    {            
        BLUser.User.UserDTO user = new BLUser.User.UserDTO();
        user.UserName = "mohan";
        user.UserPassword = "abc";
        BLUser.Model.Fs_User result = BLUser.User.LoginUser(user);
        Assert.AreEqual("mohan", result.UserName);
    }

我的业务逻辑是,

 public static Fs_User LoginUser(UserDTO userDTO)
    {                                   
        try
        {
            var context = new UserDBEntities();
            {                    
                var LoginUser = context.Fs_User.Where(u => u.UserName == userDTO.UserName && u.UserPassword == userDTO.UserPassword).SingleOrDefault();
                if (LoginUser == null)
                    ValidationError.LoginException((int)ExceptionCodes.InvalidPassword);
                return LoginUser;
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }                        
    }

1 个答案:

答案 0 :(得分:3)

请在此处查看我的回答:Solid Principle examples anywhere?

如果你想看一下依赖于数据访问界面的想法,你就会看到如何提供一个虚假的'用于测试的接口的实现,不依赖于数据库。

根据您的示例,您需要进行以下更改:

public class LoginThing
{
    private readonly IAmSomeContext context;

    public LoginThing(IAmSomeContext context)
    {
        this.context = context;
    }

    public Fs_User LoginUser(UserDTO userDTO)
    {                                   
        try
        {
            var LoginUser = 
                this.context.Fs_User
                    .SingleOrDefault(
                       u => 
                           u.UserName == userDTO.UserName 
                           && u.UserPassword == userDTO.UserPassword);

            if (LoginUser == null)
                ValidationError.LoginException((int)ExceptionCodes.InvalidPassword);

            return LoginUser;
        }
        catch (Exception ex)
        {
            throw ex;
        }                        
    }
}

然后你的测试就会变成:

[TestMethod]
public void _01_LoginUser_01_Valid()
{            
    BLUser.User.UserDTO user = new BLUser.User.UserDTO();
    user.UserName = "mohan";
    user.UserPassword = "abc";

    var fakeContext = CreateFakeContextWith(user);

    var thingUnderTest = new LoginThing(fakeContext);

    BLUser.Model.Fs_User result = thingUnderTest.LoginUser(user);

    Assert.AreEqual("mohan", result.UserName);
}

如果使用NSubstitute:

,创建虚假上下文就像这样
private IAmSomeContext CreateFakeContextWith(BLUser.User.UserDTO user)
{
    var fakeContext = Substitute.For<IFakeContext>();

    fakeContext.Fs_User.Returns(new List(new[] {user}));

    return fakeContext;
}

语法可能不完全正确,但你明白了......