簡単な要約として、これを本当にテスト可能にしたい場合は、次をお勧めします。
- データ フォーマット コードを新しいクラス (モックに使用できるインターフェイスを実装するクラス) に抽出します。
- このクラスを渡すと、
DataSet
.
- 新しいクラス
が、モックもできる
DataSet
as を返すようにします。IXmlSerializable
現在のコードを見ずに、いくつかの仮定を立てる必要があります (あまり多くないことを願っています!) - おそらく、現在のコードは次のようになります。
public class EmployeeService {
private IEmployeeRepository _Repository;
public EmployeeService(IRepository repository) {
this._Repository = repository;
}
public void ExportEmployeeData(int employeeId, string path) {
DataSet dataSet = this._Repository.Get(employeeId);
// ... Format data in the dataset here ...
dataSet.WriteXml(path);
}
}
このコードはシンプルで効果的ですが、テストできません (副作用なし)。さらに、そのすべてのロジックを 1 か所にまとめることは、単一責任の原則に違反します。
あなたのニーズにもよりますが、おそらく大丈夫です!SRP を満たすことは常に単なる目標であり、設計に影響を与える他の要因とテスト容易性のバランスを取る必要があります。
ただし、責任をもう少し分離してテスト可能にしたい場合は、書式設定ロジックを独自のクラス ( を実装するIEmployeeDataSetFormatter
) に移動してIEmployeeDataSetFormatter
から、このメソッド呼び出しに を挿入します (または、のように、サービスのコンストラクターIEmployeeRepository
)。データをフォーマットするメソッドは を返すIXmlSerializable
ので、安全で分離されたテストのためにモックを作成できます。
public interface IEmployeeDataSetFormatter {
IXmlSerializable FormatForExport(DataSet dataSet);
}
public class EmployeeDataSetFormatter: IEmployeeDataSetFormatter {
public IXmlSerializable FormatForExport(DataSet dataSet) {
// ... Format data in the dataset here ...
return (IXmlSerializable) dataSet;
}
}
public void ExportEmployeeData2(int employeeId, string path, IEmployeeDataSetFormatter formatter) {
DataSet dataSet = this._Repository.Get(employeeId);
IXmlSerializable xmlSerializable = formatter.FormatForExport(dataSet);
// This is still an intermediary step - it's probably worth
// moving this logic into its own class so you don't have to deal
// with the concrete FileStream underlying the XmlWriter here
using (XmlWriter writer = XmlWriter.Create(path)) {
xmlSerializable.WriteXml(writer);
}
}
これには明確なコストがかかります。追加のインターフェイス、追加のクラス、およびもう少し複雑さが追加されます。しかし、それはテスト可能で、よりモジュール化されています (良い意味で、私はそう思います)。