以下のようにコードをリファクタリングすることで、テスト専用の Sqlite データベースを非常に簡単に挿入できます。しかし、どのように結果を主張していますか? ビジネス オブジェクトは に渡されsomeOtherClass
ます。を注入する場合ISomeOtherClass
、そのクラスのアクションも表示される必要があります。ちょっと痛そうです。
public class KillerApp
{
private String databasePath;
private ISomeOtherClass someOtherClass;
public KillerApp(String databasePath, ISomeOtherClass someOtherClass)
{
this.databasePath = databasePath;
this.someOtherClass = someOtherClass;
}
public void DoThatThing()
{
var connection = OpenSqliteConnection(databasePath);
var allGizmoRecords = connection.Query(...);
var businessObjects = TransformIntoBizObjs(allGizmoRecords);
someOtherClass.HandleNewBizObjs(businessObjects);
}
}
[TestClass]
public class When_Doing_That_Thing
{
private const String DatabasePath = /* test path */;
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;
[TestInitialize]
public void TestInitialize()
{
app = new KillerApp(DatabasePath, someOtherClass);
}
[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}
を使用すると、このクラスからコードの一部が削除されるため、実装IRepository
をモックしたり、テスト用に偽装したりできます。IRepository
public class KillerApp
{
private IRepository<BusinessObject> repository;
private ISomeOtherClass someOtherClass;
public KillerApp(IRepository<BusinessObject> repository, ISomeOtherClass someOtherClass)
{
this.repository = repository;
this.someOtherClass = someOtherClass;
}
public void DoThatThing()
{
BusinessObject[] entities = repository.FindAll();
someOtherClass.HandleNewBizObjs(entities);
}
}
[TestClass]
public class When_Doing_That_Thing
{
private const String DatabasePath = /* test path */;
private IRepository<BusinessObject> repository;
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;
[TestInitialize]
public void TestInitialize()
{
repository = new BusinessObjectRepository(DatabasePath);
app = new KillerApp(repository, someOtherClass);
}
[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}
しかし、これはまだかなり面倒に感じます。理由は 2 つあります。1)最近、Ayendeから、Repository パターンが悪い評判を受けて います。そして 2)独自のデータアクセスを書いて何をしているのですか!? NHibernateとActiveRecordを使用してください。
[ActiveRecord] /* You define your database schema on the object using attributes */
public BusinessObject
{
[PrimaryKey]
public Int32 Id { get; set; }
[Property]
public String Data { get; set; }
/* more properties */
}
public class KillerApp
{
private ISomeOtherClass someOtherClass;
public KillerApp(ISomeOtherClass someOtherClass)
{
this.someOtherClass = someOtherClass;
}
public void DoThatThing()
{
BusinessObject[] entities = BusinessObject.FindAll() /* built-in ActiveRecord call! */
someOtherClass.HandleNewBizObjs(entities);
}
}
[TestClass]
public class When_Doing_That_Thing : ActiveRecordTest /* setup active record for testing */
{
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;
[TestInitialize]
public void TestInitialize()
{
app = new KillerApp(someOtherClass);
}
[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}
その結果、クラスが大幅に小さくなり、ビジネス オブジェクトとデータ層がより簡単に変更できるようになります。また、データベース呼び出しをモックする必要さえありません。ActiveRecord を構成および初期化して、テスト データベース (メモリ内でも) を使用することができます。