繁体   English   中英

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

[英]NoSQL - How to mock database for unit testing?

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

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

假设我们有一个 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.
    }

}

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

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

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

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

与模拟任何依赖项的方式相同。 编写一个漂亮、整洁的合约,可以从中抽象出实现细节,然后模拟该合约。 通常这是通过使用数据访问层作为合同来完成的。
在不深入了解实际实现细节的情况下,假设您在要测试的方法中有一个查询:(注意,我从 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 本地主机上的数据库。现在,如果您将此逻辑分离到另一个 class 中:

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 这样的框架模拟

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM