NoSQL データベースについて調べていて、単体テストについて質問があります。ビジネス ロジックを単体テストするための適切な方法は何ですか? NoSQL データベースをどのようにモックしますか?
3 に答える
ビジネス ロジックはデータベースに直接触れるのではなく、データベース アクセス レイヤーを通過する必要があります。これにより、単体テスト用にその中間層をモックできます。これを行うには、依存関係の挿入とモックを使用できます。これらの両方に役立つフレームワークがありますが、手動で行うこともできます。次に例を示します。
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.
}
}
したがって、本番コードでは、デフォルトのコンストラクターを使用してビジネス クラスを作成します。これにより、DB に接続されたクラスが自動的に作成されます。ただし、指定した IDataProvider を使用して BusinessClass を作成できることに注意してください。したがって、テスト用に「偽の」データ プロバイダーを作成できます。
public class MockDataProvider: IDataProvider
{
public string getData()
{
//return some expected result that you can control, without doing a DB call.
}
}
テストで、新しい MockDataProvider を作成し、それを BusinessClass のコンストラクターに渡すことができます。ビジネス クラスは、実際の DB ではなく、モック データ プロバイダーを使用するようになります。
ここではすべて手作業で行いましたが、これがどのように機能するかを理解するのに役立ちます。実際には、モックと依存性注入フレームワークを使用して、そのコードの束を作成できます。
依存関係をモックするのと同じ方法です。実装の詳細を抽象化できるきちんとしたコントラクトを作成し、そのコントラクトをモックします。通常、これはコントラクトとしてデータ アクセス レイヤーを使用して行われます。
実際の実装の詳細には触れずに、メソッドにテストしたいクエリがあるとしましょう: (注: このコードは ravenDB の例からコピーしましたが、ravenDB については何も知らないので、コンパイルさえできない可能性があります)
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 に db が必要なため、モック/テストするのはかなり難しくなります。ここで、このロジックを別のクラスに分離すると、次のようになります。
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などのフレームワークで簡単にモック化したりできます。
すでに投稿された (正しい) 回答に加えて、別の解決策を提案させてください: 実際の開発データベースを使用してください! 本物ほどリアルなモックはありません。直接テストすると、少なくともコードが実際に実行されることがわかります。
ただし、データベースを簡単に抽象化できる場合は、そうすることをお勧めします。