6

我正在研究 NoSQL 数据库并且对单元测试有疑问。对业务逻辑进行单元测试的合适方法是什么?如何模拟 NoSQL 数据库?

4

3 回答 3

2

您的业​​务逻辑不应直接接触数据库,而应通过数据库访问层。这使您可以模拟该中间层以进行单元测试。为此,您可以使用依赖注入和模拟。有一些框架可以帮助您完成这两件事,但您也可以手动完成。这是一个例子:

假设我们有一个 DAL:

public class DBDataProvider: IDataProvider
{
    public string getData()
    {
         //SQL to get data from actual database.
    }
}

如您所见,这实现了一个接口,用于为您的业务层提供数据。它可能看起来像这样:

public Interface IDataProvider
{
     String getData();
}

您的业​​务层可能如下所示:

public BusinessClass
{
    private IDataProvider dataProvider;

    public BusinessClass()
    {
        dataProvider = new DBDataProvider();
    }

    public BusinessClass(IDataProvider provider)
    {
        dataProvider = provider;
    }

    public void doBusinessStuff()
    {
        dataProvider.getData(); 
        //Do something with data.
    }

}

因此,现在在您的生产代码中,您将使用默认构造函数创建业务类,这将自动使您的类与数据库连接。但是,请注意,我们可以使用我们指定的 IDataProvider 创建一个 BusinessClass。因此,您可以制作一个“假”数据提供者仅用于测试:

public class MockDataProvider: IDataProvider
{
    public string getData()
    {
         //return some expected result that you can control, without doing a DB call.
    }
}

现在在您的测试中,您可以创建一个新的 MockDataProvider,并将其传递给 BusinessClass 的构造函数。您的业​​务类现在将使用您的模拟数据提供程序,而不是真正的数据库。

在这里,我手工完成了所有操作,但它让您了解了它是如何工作的。在现实生活中,您可以使用模拟和依赖注入框架为您编写一堆代码。

于 2012-04-06T19:27:13.760 回答
1

就像你模拟任何依赖一样。编写一个漂亮、简洁的合约,从中可以抽象出实现细节,然后模拟该合约。通常这是通过将数据访问层用作合同来完成的。
在不深入了解实际实现细节的情况下,假设您在要测试的方法中有一个查询:(注意,我从 ravenDB 示例中复制了此代码,但我对 ravenDB 的了解为 0,因此它甚至可能无法编译)

public void SomeMethod()
{
    var name = "Hello";
    var motto = "World";                       
    using (var docStore = new DocumentStore("localhost", 8080).Initialize())
    using (var session = documentStore.OpenSession()){
        session.Store(new Company { Name = name, Motto = motto });;
        session.SaveChanges();
    }
}

这将很难模拟/测试,因为它需要 8080 上 localhost 上的数据库。现在,如果您将此逻辑分离到另一个类中:

public class AwesomeDAL
    public virtual void AddCompany(string name, string motto){
        using (var docStore = new DocumentStore("localhost", 8080).Initialize())
        using (var session = documentStore.OpenSession()){
            session.Store(new Company { Name = name, Motto = motto });;
            session.SaveChanges();
        }
}

并允许注入依赖项(AwesomeDal):

public class ClassBeingTested
{
    public AwesomeDal DAL { get; set; }
    public ClassBeingTested() : this(new AwesomeDal()){}
    public ClassBeingTested(AwesomeDal dal)
    {
       this.DAL = dal;
    }

    public void SomeMethod()
    {
        var name = "Hello";
        var motto = "World";                       
        this.DAL.AddCompany(name, motto);
    }
}

您现在可以单独测试 BL 代码。或者你可以模拟数据库异常,或者任何你需要测试的东西,因为你的数据访问层是抽象的,并且它的实现很容易用像Moq或 RhinoMocks这样的框架来模拟

于 2012-04-06T19:28:01.423 回答
0

除了已经发布的(正确)答案之外,让我提出一个替代解决方案:使用真正的开发数据库!没有什么比真实的东西更真实的模拟了。如果您直接对其进行测试,至少您知道您的代码将实际运行。

如果您可以轻松地抽象出您的数据库,我建议您这样做。

于 2012-04-06T21:48:48.887 回答