NoSQL - 如何模拟数据库进行单元测试?

时间:2012-04-06 19:25:02

标签: c# .net nosql

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

3 个答案:

答案 0 :(得分: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的构造函数。您的业​​务类现在将使用您的模拟数据提供程序,而不是真正的数据库。

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

答案 1 :(得分: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等框架可以轻松模拟其实现

答案 2 :(得分:0)

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

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