1

データベースに何かを(間接的に)書き込むメソッドの単体テストを書きたいので、フレームワークのモックを手に入れ始めました。クラス構造の小さな例を次に示します。

class SomePersistenceClass
{
    public void Persist(object value, string type)
    {
        if (type.Equals("Numeric"))
        {
            PersistNumeric( (int)value );
        }
    }

    private void PersistNumeric(int number)
    {
        //Some Calculations and Creation of DBObject
        number++;
        var dbObject = new DatabaseObject {DbObjectData = new DatabaseObjectData {Number = number, Creator = "John Doe"}};
        PersistImpl(dbObject);
    }

    private void PersistImpl(IDatabaseObject dbObject)
    {
        try
        {
            dbObject.Save();
        }
        catch (Exception)
        {
            //ErrorHandling
            throw;
        }
    }
}

interface IDatabaseObject
{
    DatabaseObjectData DbObjectData { get; set; }
    void Save();
}

class DatabaseObject : IDatabaseObject
{
    public DatabaseObjectData DbObjectData { get; set; }

    public void Save()
    {
        //Save to Database;
    }
}

class DatabaseObjectData
{
    public int Number { get; set; }
    public string Text { get; set; }
    public string Creator { get; set; }
}

私が今やりたいことは、public persist メソッドをテストすることです。ここでの問題は、私の DatabaseObject がデータをデータベースに保存することです。DatabaseObject の save メソッドをモックするのは簡単ですが、モックされたオブジェクトを PersistImpl に挿入する最良の方法がわかりません (ご覧のとおり、パブリック メソッドの DatabaseObject に関する知識はありません)。方法。1 つの考えは、DatabaseObject の作成を public メソッドにプルアップすることでした。だから、このようなもの:

    public void Persist(object value, string type, IDatabaseObject dbObject)
    {
        if (type.Equals("Numeric"))
        {
            PersistNumeric( (int)value, dbObject );
        }
    }

    private void PersistNumeric(int number, IDatabaseObject dbObject)
    {
        //Some Calculations and Creation of DBObject
        number++;
        dbObject.DbObjectData.Number = number;
        dbObject.DbObjectData.Creator = "John Doe";
        PersistImpl(dbObject);
    }

しかし、私はこの魂にかなり不満です。永続化クラスの外部でデータベース オブジェクトを作成する必要があります。

このような問題を解決する良い方法はありますか?単体テスト内でデータベースへのアクセスを確実に削除する必要があります。

4

1 に答える 1

1

問題を解決する 1 つの方法は、DatabaseObjectオブジェクトの構築をファクトリ クラスに委譲することです。

interface IDatabaseObjectFactory
{
    IDatabaseObject Create(DatabaseObjectData data);
}

class DatabaseObjectFactory : IDatabaseObjectFactory
{
    public IDatabaseObject Create(DatabaseObjectData data)
    {
        return new DatabaseObject {DbObjectData = data };
    }
}

class SomePersistenceClass
{
    readonly IDatabaseObjectFactory _factory;

    public SomePersistenceClass()
    {
        _factory = new DatabaseObjectFactory();
    }

    public SomePersistenceClass(IDatabaseObjectFactory factory)
    {
        _factory = factory;
    }

    public void Persist(object value, string type) { /* ... */ }
    private void PersistImpl(IDatabaseObject dbObject) { /* ... */ }

    private void PersistNumeric(int number)
    {
        //Some Calculations and Creation of DBObject
        number++;
        var dbObject = _factory.Create(new DatabaseObjectData {Number = number, Creator = "John Doe"});
        PersistImpl(dbObject);
    }

}

ここで、クラスをテストする場合、データベースにアクセスしないFakeDatabaseObjectFactoryを返すを渡すことができます。FakeDatabaseObject

(ただし、クラスでデータベース アクセスを処理する方法は少しわかりませんDatabaseObject... 奇妙ですが、それは別のトピックです)。

于 2013-09-12T12:43:50.550 に答える