2011-07-24 12 views
3

DataBaseConfigurationクラスに依存するStoreManagerクラスの機能をテストしています。テスト中のクラスの.NETへの依存性注入

public class StoreManager { 
    private DataBaseConfiguration dbConfig; 
    public void Store(string name) { 
    dbConfig.Store(name); 
    } 
    //other methods here 
} 

StoreManagerクラスはデータベースに格納され、このメソッドが正常に動作するかどうかをテストする唯一の方法は、データベースからのクエリです。私はそれを行う生産で別のクラスを持っている..私はstoredvaluesをテストするためにQueryManagerクラスを使用する必要があるよう

public class QueryManager { 
private DataBaseConfiguration dbConfig; 
public string Query(QueryExpression expr) { 
    //query logic 
    string name = "somename"; 
    return name; 
}} 

は本家の私はそれが私には見えますテストだけ私のStoreManagerクラスと心配です。 は、あなたが見ることができるように、私はこのような基本的なテストケース...

[TestFixture] 
public class StoreManagerTest { 
[TestFixtureSetup] 
public void Setup() { 
    DatabaseConfiguration dbConfig = new DatabaseConfiguration(/*test database details*/); 
    StoreManager sm = new StoreManager(dbConfig); 
    QueryManager qm = new QueryManager(dbConfig); 
} 

[Test] 
public void TestStore_ValidStore() { 
    sm.Store("testname"); 
    string queryResult = qm.Query(new QueryExpression("query_expr")); 
    Assert.AreSame(queryResult, "testname"); 
}} 

を持って、離れて(StoreManagerです)ClassUnderTestから、QueryManagerクラスもDatabaseConfigに依存しています。

私はStoreManagerクラスの内部ロジックの多くを持っていない、DataBaseConfigクラスに、それだけで代表が良く、実際に実際にデータを記憶する記憶に関わるいくつかの複数のクラス、そのないDataBaseConfigがあります(保存します..

このテストは、QueryManagerをまったく使用せずに処理する方が良いかどうかを知りたいですか? また、DataBaseConfigurationへの依存関係をStoreManagerクラスに挿入するより良い方法があります(DataBaseConfigurationクラスがデータを格納するデータベースの接続文字列などの詳細を考慮していることを考慮してください)。そこに本番データベース接続文字列ではなくテストデータベース)を作成します。

答えて

5

最も一般的なアプローチをテストする際に依存関係を取得するには、手書きのスタブまたはモックフレームワーク(MoqまたはRhinoMocks)を使用する方法があります。

さらに、StoreManagerクラスのユーザーがDataBaseConfiguration依存関係を通過できるようにする必要があります。そうしないと、コードを変更せずにスタブすることができません。あなたが今行っているようにコンストラクタを注入するのは一般的な方法で、これを行うためのきれいな方法です(多くの依存関係があるときにIOCコンテナを使用すると便利です)。hereも参照してください。私が正しくあなたを理解していれば

、あなただけの、あなたがStoreManagerの行動とその依存DataBaseConfigurationとの相互作用に興味があるStoreManagerが実際にあなたがそれに渡す値を格納することをテストしたい - 今あなたがすることによってそれを行います検証のためにデータストア自体に照会します。

私が変更した唯一の事は、DataBaseConfigurationクラスのStoreメソッドを仮想として定義していたため、RhinoMocksがオーバーライドできるようにしました。

//Arrange 
string storeValue = "testname"; 
var dbConfigMock = MockRepository.GenerateMock<DataBaseConfiguration>(); 
dbConfigMock.Expect(x => x.Store(storeValue)); 
StoreManager sm = new StoreManager(dbConfigMock); 

//Act 
sm.Store(storeValue); 

//Assert 
dbConfigMock.AssertWasCalled(x => x.Store(storeValue)); 

このテストでは、ストアメソッドが他の依存性O/WあなたDataBaseConfigurationクラスに呼び出されたことを確認する - それはあなたのStoreManagerクラスの振る舞いをテストします。このテストはDBには触れず、他のクラスにも影響しません。

編集:

私は、生産コードでモックフレームワークを使用して懸念を理解していない - モックフレームワークは、あなたのテストプロジェクト、それへの参照、または任意のコードで使用されていますプロダクションコード自体に変更が必要です。あなたが「手動」に同じアサーションを行うことができます手書きのスタブを使用して

:もう一度、これはそれを無効にすることができるので、仮想宣言するStore方法を必要回数とStore()が呼び出されたどのような値で(保存するテストスタブを定義します):

​​

今の代わりにDataBaseConfiguration "本物" のテストでは、このテストスタブを使用します。

string storeValue = "testname"; 
DataBaseConfigurationTest dbConfigStub = new DataBaseConfigurationTest(); 
StoreManager sm = new StoreManager(dbConfigStub); 

sm.Store(storeValue); 

Assert.AreEqual(1, dbConfigStub.TimesCalled); 
Assert.AreEqual(storeValue, dbConfigStub.LastNameStored); 
+0

説明してくれてありがとう! Rhino Mocksをプロダクションコードで使用できるかどうかはわかりません(http://builds.hibernatingrhinos.com/builds/Rhino-MocksからRhinoをダウンロードし、私のソースにRhino.Mocks.dllを参照する必要があるように見えます)コード)。この場合、手書きのスタブがどのように見えるかについてのいくつかの指針を与えますか? – Santhosh

+0

@サントシー:あなたのサンプルに手書きのスタブを付けて更新 – BrokenGlass

+0

サンプルコードはありがとう! – Santhosh