如何在Visual Studio测试中模拟数据存储库?

怪物

我是单元测试的新手。我有这些类AccountBl,它们调用使用SqlConnection的DataStore来从数据库中获取数据。

我需要通过模拟数据源来测试AccountBl.GetInvestmentAccounts方法,即使没有数据库连接也需要运行测试。

这是给定的类AccountBl

public class AccountBl
{
    private readonly DataStore dataStore = new DataStore();

    public List<Account> GetInvestmentAccounts(int clientId, AccountType accountType)
    {
        if (accountType == AccountType.Investment)
        {
            var accounts = dataStore.LoadAccounts(clientId);
            return accounts.Where(a => a.AccountType == AccountType.Investment).ToList();
        }
        throw new Exception("Invalid account type provided");
    }
}

数据存储

public class DataStore
{
    public static string GetAccountsSql = "irrelevant query";

    public virtual List<Account> LoadAccounts(int clientId)
    {
        using (var connection = CreateConnection())
        {
            var sqlCommand = connection.CreateCommand();
            sqlCommand.CommandText = GetAccountsSql;
            sqlCommand.CommandType = CommandType.Text;
            sqlCommand.Parameters.Add("@clientId", clientId);

            var reader = sqlCommand.ExecuteReader();
            var accounts = new List<Account>();
            while (reader.Read())
            {
                var account = new Account();
                account.AccountNumber = (string)reader["number"];
                account.AccountOwner = clientId;
                if (reader["accountType"] == null || reader["accountType"] == DBNull.Value)
                {
                    account.AccountType = AccountType.Checking;
                }
                else
                {
                    account.AccountType =
                        (AccountType)Enum.Parse(typeof(AccountType), reader["accountType"].ToString());
                }
                accounts.Add(account);
            }
            return accounts;
        }

    }

    private static SqlConnection CreateConnection()
    {
        var sqlConnection = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"]);
        sqlConnection.Open();
        return sqlConnection;
    }
}

这是我的TestClass

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void GetInvestmentAccountsTest()
    {
        var clientId = 25;

        var mockAccounts = new List<Account>
        {
            new Account{AccountNumber = "aaa", AccountOwner = clientId, AccountType = AccountType.Investment},
            new Account{AccountNumber = "bbb", AccountOwner = clientId, AccountType = AccountType.Savings},
            new Account{AccountNumber = "ccc", AccountOwner = clientId, AccountType = AccountType.Checking},
        };

        var mockDatastore = new Mock<DataStore>();
        mockDatastore.Setup(x => x.LoadAccounts(clientId)).Returns(mockAccounts);

        var accountBl = new AccountBl();

        var accounts = accountBl.GetInvestmentAccounts(clientId, AccountType.Investment);


    }
}

运行时,我收到错误消息

消息:测试方法ScreeningSample.Tests.UnitTest1.GetInvestmentAccountsTest引发了异常:System.InvalidOperationException:ConnectionString属性尚未初始化。

显然,它试图创建一个连接,但是我需要在没有连接的情况下运行测试。

我在嘲笑吗?

恩科西

所述readonly DataStore dataStore待测对象被紧密地结合到类,使得难以隔离测试的主题。您将需要能够在测试期间替换该依赖性,以便能够进行独立测试。

考虑首先抽象化数据存储,

public interface IDataStore {
    List<Account> LoadAccounts(int clientId);
}

并且让主题明确地通过构造函数注入依赖于该抽象,因为类应该依赖于抽象而不是依赖于具体概念。

public class AccountBl {
    private readonly IDataStore dataStore;

    public AccountBl(IDataStore dataStore) {
        this.dataStore = dataStore;
    }

    public List<Account> GetInvestmentAccounts(int clientId, AccountType accountType) {
        if (accountType == AccountType.Investment) {
            var accounts = dataStore.LoadAccounts(clientId);
            return accounts.Where(a => a.AccountType == AccountType.Investment).ToList();
        }
        throw new Exception("Invalid account type provided");
    }
}

SqlConnection 是不再需要关注的实现细节 AccountBl

DataStore实现将从抽象派生。

public class DataStore : IDataStore {

    public List<Account> LoadAccounts(int clientId) {
        //...code removed for brevity
    }

    //...
}

现在,代码已解耦,可以更灵活地进行隔离测试了

[TestClass]
public class UnitTest1 {
    [TestMethod]
    public void GetInvestmentAccountsTest() {
        //Arrange
        var clientId = 25;
        var mockAccounts = new List<Account> {
            new Account{AccountNumber = "aaa", AccountOwner = clientId, AccountType = AccountType.Investment},
            new Account{AccountNumber = "bbb", AccountOwner = clientId, AccountType = AccountType.Savings},
            new Account{AccountNumber = "ccc", AccountOwner = clientId, AccountType = AccountType.Checking},
        };

        var mockDatastore = new Mock<IDataStore>();
        mockDatastore.Setup(_ => _.LoadAccounts(clientId)).Returns(mockAccounts);

        var subject = new AccountBl(mockDatastore.Object);

        //Act
        var accounts = subject.GetInvestmentAccounts(clientId, AccountType.Investment);

        //Assert
        //...
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Service for Unit测试中存储库的模拟方法如何测试

如何在测试中模拟慢速SQL数据库?

如何在Visual Studio中连接Oracle数据库

如何使用模拟存储库测试CRUD?

如何在Android Studio中更改Visual Studio Team Services存储库?

如何在Visual Studio代码中忽略整个git存储库?

如何在Visual Studio 2012中将数据添加到Access数据库

如何在Java中模拟MongoDB存储库方法

如何在Visual Studio Code中调试Karma测试?

如何在Visual Studio中运行XUnit测试?

如何在Visual Studio中调试TypeScript单元测试?

如何在Visual Studio 2017中运行NUnit测试?

如何在Visual Studio Team Services中运行NUnit测试

如何在Visual Studio 2013中存储未提交的更改

如何将我的 Android 项目的数据库文件从 Android Studio 4.2.2 中的 Genymotion 模拟器设备提取到本地 PC 以进行测试?

如何在Visual Studio 2017中使用Qt库?

如何在Visual Studio 2015中添加库,头文件

如何在C ++中设置json库?(Microsoft Visual Studio)

如何在visual studio中添加图形库?

如何在VS 2015中发布Visual Studio数据库项目

如何在Visual Studio 2013中创建SQL Server数据库项目?

如何在Visual Studio 2010中使用phpmyadmin数据库?

如何在 Visual Studio 中创建一个已经存在的数据库?

如何在Visual Studio 2010(基于服务的数据库)中添加新表?

如何在Visual Studio 2015中为SQL Server创建数据库图?

单元测试如何使用Mockito模拟存储库

如何模拟Save方法的行为来测试我的存储库?

如何在测试类中模拟JNDI数据源

在游戏功能测试中可以模拟数据库连接吗?如何进行?