非常にうまく設計されていると思われるコードを書いたことがありますが、そのコードの単体テストを書き始めて、確信が持てなくなってしまいました。
合理的な単体テストを作成するには、変数アクセス修飾子の一部を から に変更する必要があることがわかりましprivate
たdefault
。つまり、それらを公開します (パッケージ内のみですが、それでも...)。
問題のコードの大まかな概要を次に示します。何らかの外部 Web サービスや DB 内のデータ、またはその他のソースによってアドレスを検証するなど、さまざまな手段でアドレス検証を可能にする、ある種のアドレス検証フレームワークがあるはずです。つまりModule
、アドレスを検証するための別の方法です。私はインターフェースを持っています:
interface Module {
public void init(InitParams params);
public ValidationResponse validate(Address address);
}
リクエストまたはセッション状態に基づいて適切なモジュールを選択する、ある種のファクトリがあります。
class ModuleFactory {
Module selectModule(HttpRequest request) {
Module module = chooseModule(request);// analyze request and choose a module
module.init(createInitParams(request)); // init module
return module;
}
}
そして、Module
検証のためにいくつかの外部 Web サービスを使用する を作成し、そのように実装しました。
WebServiceModule {
private WebServiceFacade webservice;
public void init(InitParams params) {
webservice = new WebServiceFacade(createParamsForFacade(params));
}
public ValidationResponse validate(Address address) {
WebService wsResponse = webservice.validate(address);
ValidationResponse reponse = proccessWsResponse(wsResponse);
return response;
}
}
したがって、基本的にはこれWebServiceFacade
が外部 Web サービスのラッパーであり、モジュールがこのファサードを呼び出し、その応答を処理し、フレームワーク標準の応答を返します。
WebServiceModule
プロセスが外部 Web サービスから正しく応答するかどうかをテストしたいと考えています。明らかに、単体テストで実際の Web サービスを呼び出すことはできないため、モックを作成しています。しかし、モジュールがモックされた Web サービスを使用するにはwebservice
、外部からフィールドにアクセスできる必要があります。それは私のデザインを壊し、それについて何かできることはないかと考えています. 明らかに、ファサードは init パラメーターで渡すことができませんModuleFactory
。
依存性注入がそのような問題の解決策になる可能性があると読みましたが、その方法がわかりませんか? Guiceなどの DI フレームワークを使用したことがないため、この状況で簡単に使用できるかどうかはわかりません。しかし、多分それはできますか?
それとも、デザインを変更する必要がありますか?
それとも、この不運なフィールド パッケージを非公開に// default visibility to allow testing (oh well...)
しますか?
ばっ!これを書いているときに、コンストラクターの引数としてWebServiceProcessor
を受け取る を作成し、 . これは私の問題に対する解決策の1つです。あなたはそれについてどう思いますか?これには 1 つの問題があります。その場合、すべての作業を別のコンポーネントに委譲するだけで、役に立たなくなるからです。WebServiceFacade
WebServiceProcessor
WebServiceModule