4

我是使用 Mocks 的新手。但它的主要目的是什么?我将首先使用 Moq 来测试我的应用程序(和 NUnit)。

例如,我有这样的代码:

我的网页代码在后面:

public partial class MyWebpage
{
    protected string GetTitle(string myVar)
    {
        return dataLayer.GetTitle(myVar);
    }
}

我的数据访问层:

public class DataLayer
{
    public string GetTitle(string myVar)
    {
        // Create the query we want
        string query = "SELECT title FROM MyTable " + 
            "WHERE var = @myVar";

        //ENTER PARAMETERS IN HERE

        // Now return the result to the view
        return this.dataProvider.ExecuteMySelectQuery(
            dr =>
            {
               //DELEGATE DATA READER PASSED IN AND TITLE GETS RETURNED
            },
            query,
            parameters);
    }
}

我的数据提供者直接与数据库对话和交互:

 public class DataProvider
{
     public T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters)
    {
          //RUNS AND RETURNS THE QUERY
     }
}

测试所有这些的最佳方法是什么?

4

2 回答 2

3

如果要单独测试层,则需要为 DataProvider 和 DataLayer 类创建接口,以公开要模拟的方法。然后你可以使用一个模拟框架——NSubstitute 非常好,创建模拟的代码更少——模拟对依赖类的调用,让你在特定单元内测试代码

public interface IDataProvider
{
     T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters);
}

public interface IDataLayer
{
    string GetTitle(string myVar);
}

public class DataLayer 
{
    private IDataProvider dataProvider;

    public DataLayer(IDataProvider dataProvider)
    {
        this.dataProvider = dataProvider;
    }
}

然后,在您的测试代码中,您创建模拟而不是真实对象,并在实例化测试对象时将它们传递给构造函数。测试数据层:

[Test]
public void WhenRetievingTitleFromDataStore_ThenDataLayerReturnsTitle() 
{
    var title = "Title";
    var dataProviderMock = new Mock<IDataProvider>(MockBehavior.Strict);
    dataProviderMock.Setup(x => x.ExecuteMySelectQuery(<parameters>)).Returns(title);
    var dataLayer = new DataLayer(dataProviderMock.Object);
    Assert.That(dataLayer.GetTitle(It.IsAny<string>(), Is.EqualTo(title));
}
于 2012-12-07T08:41:09.277 回答
2

唯一可能出错的是数据库调用(查询或返回的结果是错误的数据类型)。这是不能嘲笑的。您需要进行集成测试而不是单元测试。

通常,您只模拟能够测试代码中的逻辑。例如,您应该进行测试,以便数据映射器 ( this.dataProvider.ExecuteMySelectQuery) 按定义工作。但这属于相关代码的范围。

更新

所以你有以下课程:

public class DataLayer
{
    public string GetTitle(string myVar)
    {
        // Create the query we want
        string query = "SELECT title FROM MyTable " + 
            "WHERE var = @myVar";

        //ENTER PARAMETERS IN HERE

        // Now return the result to the view
        return this.dataProvider.ExecuteMySelectQuery(
            dr =>
            {
               //DELEGATE DATA READER PASSED IN AND TITLE GETS RETURNED
            },
            query,
            parameters);
    }
}

public class DataProvider
{
     public T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters)
    {
          //RUNS AND RETURNS THE QUERY
     }
}

如果我们检查一下,ExecuteMySelectQuery我们可以看到DataLayer该类依赖于数据库返回的类型,因为这DataProvider只是简化了查询执行。可以说它是 ADO.NET 之上的一个插件。

这也意味着您永远无法保证在DataLayer不涉及数据库的情况下返回所承诺的内容。例如,假设table数据库中有一个名为的列,title但有人设法改用该int数据类型。

可能出错的事情是

  • 查询不正确
  • 数据库中的架构不正确(错误的列名、数据类型等)
  • 映射

在模拟的帮助下,无法检测或测试这些错误。

另一方面,如果您DataLayer在另一个班级中使用该班级,您当然可以模拟它。因为DataLayer类本身就是一个完整的抽象。这意味着类的调用者不必知道它下面的任何东西。因此,嘲笑是完全可以的。

于 2012-12-07T08:33:03.997 回答