0

このメソッドの単体テストを行う必要があります。問題は、FsFileGroupFile が簡単にモックできないこと、複雑なコンストラクター要件があり、インターフェイスを直接使用しないことです。_blockReaderFactory一方、インターフェイスであるため、簡単にモックできます。このような複雑なオブジェクトをどのようにモックできますか。Rhino Mocks と Microsoft Unit Testing Framework を使用しています。アイデアはありますか?

    public void ReadGeneral(FsFileGroupFile a_file, FileItemData a_fileItemData)
    {
        try
        {
            var blockReader = _blockReaderFactory.Create(a_file.File.FullName, "CabinetData/StartData");

            var version = blockReader.ReadVersion();
            var name = blockReader.ReadString();
            var type = blockReader.ReadString();
            var defaultHeight = blockReader.ReadDouble();
            var defaultWidth = blockReader.ReadDouble();
            var defaultDepth = blockReader.ReadDouble();

            a_fileItemData.Name = name;
            a_fileItemData.DefaultWidth = defaultWidth * 100.0;
            a_fileItemData.DefaultHeight = defaultHeight * 100.0;
            a_fileItemData.DefaultDepth = defaultDepth * 100.0;
        }
        catch (Exception ex)
        {
            throw new IOException("General data could not be read from block data.", ex);
        }
    }
4

3 に答える 3

1

a_fileファイル名を取得するためだけに使用しているようです。では、インターフェイスFilenameSupplier(または類似のもの) を作成し、それを実装するラッパーを作成してみませんか?

Java コードの例 (質問が C# としてタグ付けされる前に追加されました...):

interface FilenameSupplier {
    String getName();
}

public void ReadGeneral(FilenameSupplier a_file, FileItemData a_fileItemData) {
    ...
    a_file.getName();
    ...
}

class ConcreteSupplier implements FilenameSupplier {
    private final FsFileGroupFile file;
    public ConcreteSupplier(FsFileGroupFile file) { this.file = file; }
    String getName() { return a_file.File.FullName; }
}
于 2013-07-25T20:44:26.667 に答える
0

からいくつかのインターフェイスを抽出しFsFileGroupFile、それをコンストラクター引数に渡す必要があります。次に、このインターフェイスをお好みのフレームワーク (あなたの場合は Rhino Mocks) で簡単にモックできます。

適切でない場合はFsFileGroupFile、複雑なコンストラクターで引数を渡すときにモックを作成し、モックを使用する必要があります。

ここで設計を確認する必要がある場合を除いて、他に選択肢はないようです。クラスのテストが非常に難しい場合は、設計が不十分である可能性があります。

于 2013-07-25T20:55:19.673 に答える
0

テストで複雑なオブジェクトを作成しなければならなかったとき、私はTest Data Builder Patternを使用しました。例として、コンストラクターに渡す値が 5 つあるとします。

public FsFileGroupFile(string firstProperty, string secondProperty,
    string thirdProperty, string fourthProperty, string fifthProperty)
{
    // constructor logic goes here
}

これは、単体テスト プロジェクトのテスト ビルダー クラスでラップされます。

public class FsFileGroupFileBuilder
{
    public string FirstProperty { get; set; }
    public string SecondProperty { get; set; }
    public string ThirdProperty { get; set; }
    public string FourthProperty { get; set; }
    public string FifthProperty { get; set; }

    public FsFileGroupFile Build()
    {
        return new FsFileGroupFile(FirstProperty, SecondProperty, ThirdProperty,
            FourthProperty, FifthProperty);
    }
}

これで、関心のあるプロパティのみに値を割り当て、次の方法でオブジェクトを構築できます。

// in your test setup use this to initial to a default/valid state
var fsFileGroupBuilder = new fsFileGroupBuilder
{
    FirstProperty = "Default",
    SecondProperty = "Default",
    ThirdProperty = "Default",
    FourthProperty = "Default",
    FifthProperty = "Default"
}

注: Rhino Mocks はおそらくこれらのデフォルト値を設定できますが、私は個人的には使用していないので、よくわかりません。

// Override the properties in each test
fsFileGroupBuilder.ThirdProperty = "Value needed for unit test."

// create
var fileItemData = new FileItemData();
ReadGeneral(fsFileGroupBuilder.Build(), fileItemData);

NBuilderなど、テスト データの生成に役立つオープン ソース ライブラリは他にもあります。

ここでの要点は、複雑なコンストラクターをビルダーで抽象化して、すべてのテストでコンストラクターを満たす代わりに、ビジネス ロジックのテストに集中できるようにすることです。

于 2013-07-25T21:12:07.833 に答える