前回までで全体のプロジェクト構成と簡単なテストコードの記述まで行いました。今回は実際にデータベースなどとのテストを実施するときに必要なRepositoryの概念を解説します。Repositoryの後にMockやMoqを使ったテストの記述方法を解説していきます
Repository
リポジトリーとはアプリケーションが外部と接触するときに外部と接触するロジックと,接触しないロジックの境目に設置するインターフェースです。データベースから値を取得するケースでは,SQLを実行するして値を返すまでが外部と接触するロジックになり,このロジックは外部との接触に必要なロジックであり,ドメイン要素ではないため,それを切り分けるためにDomainとは別にInfrastructureに切り出します。RepositoryのインターフェスはDomain層に配置します。
最終的にはDomain層のインターフェースに対してInfrastructureが実装部分を記述し,UIよりDomain層にインターフェースに対して呼び出しをします。最上位のインターフェースに対してコードを記述し,InfrastructureとUIは抽象に依存する形になります。
要するに依存関係逆転の法則です。別に新しい技術ではありません。Domainプロジェクトに「Repositories」というフォルダを作成し,その中に「ISensorRepository」というクラスを作成します。
public interface ISensorRepository { float GetData(); }
Float値を返却するGetData()という関数を一つ定義します。GetDataという関数の中でどのような技術的な実装がされるかは今は後回しにしてとにかく読んだら「Float値を返してくれるもの」というくらいに思っておいてください。
それではMeasureViewModelの実装を続けます。最初にprivate変数としてISensorRepositoryを定義します。
private ISensorRepository _sensorRepository;
そしてMeasure()メソッドの中にこう書きます。
public void Measure() { var value = _sensorRepository.GetData(); MeasureValue = Math.Round(value,2) + “m/s”; }
今作ったリポジトリーのGetData()を呼び出すと,なんだかわかりませんが,Float値 (センサーの計測値を想定している)が返ってくるという定義をしたのでそれを呼び出し,取得した値に対して小数点以下2桁で丸めて単位「m/s」をくっつけています。
いったんこれでテストしましょう。残念ながらまだレッドバーですね。どこでNGになっているのかがわからなければ,テスト項目を選択してデバッグ実行してください。
NG箇所で処理が止まります。
ちなみに今やると
_sensorRepository.GetData()
でNullExceptionが発生しています。
当然sensorRepositoryは宣言しただけなのでNullです。
ここに何かインスタンスを生成しなければなりません。
では何を生成しましょう。
まだISensorRepository のインターフェースを作成しただけで具象クラスは作成していません。
どうしましょうか?
実際にセンサー接続を行う具象クラスをInfrastructure層に作りましょうか?
そんなクラスをNewしたら実際にセンサーにつながっていないとエラーになるのではないでしょうか?
データベースへの記述と同じですね。
最初に言った通り,テストしやすいコードにしなければなりません。
インターフェースの向こう側で,技術的な解決を行うコードは本番コードです。いずれ書かなければなりませんが,今は先送りにします。ドメインに集中しましょう。ではどうやってテストしましょうか?
Mockという概念とMoqというクラスライブラリを使って
解決していきましょう。