2017-09-18 1 views
5

私は基本的に、これは私はあなたが私を見ることができるように同じクラスにあるメソッド呼び出しを模擬します。私はテストしています、実際にはコードのにおいですか?

class CarServiceImpl{ 
    public Car findById(String id){ 
     //call repository layer to find a car 
    } 

    public void deleteById(String id){ 
     Car car = this.findById(id); 
     if(car != null){ 
      //Call repository layer to update the car 
     }else{ 
      Throw NotFOundException(); 
     } 
    } 
} 

をテストしようとしているクラスである、(リポジトリ層を呼び出し、必要に応じていくつかの操作を行うための責任)サービスクラスをテストしようとしています私の質問があるので、deleteByIdメソッドのfindByIdメソッドを呼び出します。

  1. 同じクラスのメソッドを呼び出すのは本当に臭いですか?私はidで車を見つけるために別のクラスを作るべきだとは思わない。私はMockito.when(carServiceImpl.findById("car1")).thenReturn(carModel); を使用する場合、私は「deleteById」法上の「findById」への呼び出しを模擬することができ、それは私も、あまりにもidで見つけるためのレポジトリへの呼び出しを模擬する必要がありますので、メソッドを呼び出すスティルス方法

  2. 私はすでにfindByIdメソッドをテストしました。

+0

'findById'操作を' deleteById'の呼び出し元に任せてはどうでしょうか? any1が存在しないidを渡した場合、リポジトリは適切な例外をスローし、 'CarServiceImpl'はアプリケーションが理解できる何かの例外をキャッチして(必要に応じて)変換することができます。 – pedromss

答えて

4

は、これは必ずしも匂いではないですし、部分的にモックCarそうのようにすることができます

String carId = "..."; 
Car car = ...; 

CarServiceImpl car = mock(CarServiceImpl.class); 
when(car.findById(carId)).thenReturn(car);  
when(car.deleteById(carId)).thenCallRealMethod(); 

しかしあなたはdeleteById()は「本当の方法」を実行できるようにすることができれば、あなたのテストはすでに必要がありますfindById()を「実際の呼び出し」にするリポジトリがあり、追加コストなしでテストカバレッジの品質が向上します。すでにfindById()をテストしたということは、はの一部として間接的にでテストしないでください。

私はあなたが次のいずれかまたは両方を行うことを示唆している:

  • ユニットテストCarをそれを嘲笑repositoryを与え、そのメソッドのすべて
  • 機能/受け入れをテストするために嘲笑期待と検証を使用してテストをCar実際のリポジトリに与え、実際の呼び出しを使用してそれぞれのメソッドの実際の結果をアサートします。

リポジトリをドメインオブジェクトに挿入するという考えは、あなたのエンティティが自分自身をCRUDする方法を知っている「アクティブレコード」パターンを意図的に使用することです。このコードのにおいと考えることができます。ドメインオブジェクトは2つのことを知っているので、それはSRPに違反し、懸念の貧弱な分離であると考えられる可能性があります。

+0

良い答え、私のために少し余裕を残す;-) – GhostCat

1

テスト設定とテストコードを可能な限り「最小限」にしたいとします。その意味では、他の答えは正しいと言います。もしあなたが特別な設定なしでdeleteById()をテストすることができたら、それを行ってください。

そして、それはfindById()は、それ自体で、テスト・セットアップの多くを必要とする「巨大な」ものであると判明するだろう - そして、私はむしろ一歩と明確なクラスにこのメソッドの内容を入れて検討する - いくつかの種類CarIdentityServiceです。

意味:非常に頻繁に作成を開始するテストコードが複雑になる - より良い答えは、私たちの生産コードの設計を変更して戻すことです。あなたの場合、findById()コードを別のクラスにプッシュしたい場合があります。模擬そのCarServiceクラス内のファインダーオブジェクトを単純に使うことができます。

CarIdentityServiceは、CarServiceのローカルクラスまたは内部クラスです。しかし、それを導入することで、実装を合理化し、スパイビジネスに陥ることを避けることができます。

+0

ファインダーコールをどのようにリファクタリングするかについての精巧さ。 – glytching

+0

クイックカムバックをお寄せいただきありがとうございます;-) – GhostCat

+0

回答ありがとうございます。コードを別のクラスに分ける必要がありますが、このケースでは1つのクラスに固執していると思います –

関連する問題