emddudleyの優れた答えに加えて、サービスのモックを作成することで得られる最大の利点は、サービスが正しく機能しない場合に何が起こるかをテストできることです。テストの疑似コードは次のようになります。
public int AgeMinimumValue_LogsServiceError_Test()
{
ClassUnderTest uut = new ClassUnderTest();
MockService service = new MockService();
service.Throws(new TimeoutException());
MockLogger logger = new MockLogger();
try {
int age = uut.getAge(service, logger);
Assert.Fail("Exception was not raised by the class under test");
}
catch (TimeoutException) {
Assert(logger.LogError().WasCalled());
}
}
そして今あなたの実装はこの新しい要件で編集されました
public int getAge(Service s, Logger l)
{
try {
int age = s.execute(empId);
return age;
}
catch(Exception ex) {
l.LogError(ex);
throw;
}
}
他のシナリオでは、より複雑な応答に応答する必要がある可能性が高くなります。サービスがクレジットカード処理を提供した場合、成功、サービス利用不可、期限切れのクレジットカード、無効な番号などに対応する必要があります。サービスを模擬することにより、状況に適した方法でこれらのシナリオに確実に対応できます。この場合、サービスからの入力/出力を模擬する必要があります。使用するコードがすべての既知の出力で機能することを知って得られるフィードバックは、本当に意味があり、価値があります。
編集:私はあなたが既存のメソッドを変更せずにモックできるようにしたいことに気づきました。これを行うにはlocate("ageservice");
、テストでモックオブジェクトをサポートするようにメソッドを変更し、準備ができたら実際のサービスを見つける必要があります。これは、使用しているサービスの実装を取得するためのロジックを抽象化したサービスロケーターパターンのバリエーションです。そのクイックバージョンは次のようになります。
public Service locate(string serviceToLocate) {
if(testEnvironment) // Test environment should be set externally
return MockService(serviceToLocate);
else
return Service(serviceToLocate);
}
ただし、サービスの依存関係をコンストラクターに移動することをお勧めします。
public int AgeMinimumValue_LogsServiceError_Test()
{
MockService service = new MockService();
service.Throws(new TimeoutException());
MockLogger logger = new MockLogger();
ClassUnderTest uut = new ClassUnderTest(service, logger);
try {
int age = uut.getAge();
Assert.Fail("Exception was not raised by the class under test");
}
catch (TimeoutException) {
Assert(logger.LogError().WasCalled());
}
}
これで、getAgeメソッドはクラスから抽象化されているため、サービスを検索する必要がなくなりました。これは、次のような実装を完全に残しています。
public int getAge()
{
try {
// _service is a private field set by the constructor
int age = _service.execute(empId);
return age;
}
catch(Exception ex) {
// _logger is a private field set by the constructor
_logger.LogError(ex);
throw;
}
}