我正在研究NoSQL数据库,并对单元测试有疑问。对业务逻辑进行单元测试的适当方法是什么?如何模拟NoSQL数据库?
答案 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)
除了已经发布的(正确的)答案之外,让我提出一个替代解决方案:使用真正的开发数据库!真实的东西,没有什么是更真实的模拟。如果你直接测试它,至少你知道你的代码实际上会运行。
如果您可以轻松地抽象出您的数据库,我建议您这样做。