1

次のシナリオがあります。作成日設定の責任をDAOオブジェクトに委任したい。

    Class Product{
     //other fields
     Date creationDate;
    }

    Class ProductDAO{
      private GenericDAO dao;
      public void create(Product p){
         p.setCreationDate(new Date());
         dao.create(p);
      }
    }

    Class Main{
      private ProductDAO productDAO; 
      public void createProduct(){
         Product p = new Product();
         productDAO.create(p);
         LOG.debug(p.getCreationDate());
      } 
    }
  1. ここで問題となるのは、productDAOをモックしてメインクラスのcreateProductメソッドをテストするときに、作成日を設定し、ログステートメントがNullPointerExceptionをスローしないように、モックオブジェクト「productDAO」の動作を定義する方法です。
  2. 上記のアプローチは正しいと思われますか?副作用に頼るのではなく、ProductDAOクラスのcreateメソッドから更新されたProductオブジェクトを返す必要がありますか?

     Product create(Product p){
           p.setCreationDate(new Date());
           dao.create(p);
           return p;
      }
    
  3. または、Mainクラスでは、戻りオブジェクトやcreateProductメソッドの副作用に依存するのではなく、作成後にデータベースからオブジェクトを読み取る必要がありますか?この場合の唯一のことは、余分な呼び出しを行うオーバーヘッドが追加されることです。

     public void createProduct(){
         Product p = new Product();
         productDAO.create(p);
         p = productDAO.read(p.getId());
         LOG.debug(p.getCreationDate());
      } 
    

長い質問でごめんなさい。説明できたと思います。

4

3 に答える 3

2

日付が設定されているかどうかをテストする1つの方法は、argThatを使用することです。あなたは次のようなことをする必要があります

@Test
public void shouldSetCreationDateAtProductWhenCreatingIt() {
     // given
     Product product = mock(Product.class);

     // when
     dao.create(product);

     // then
     verify(product).setCreationDate(argThat(is(not(nullValue(Date.class)))));
}

Product#setCreationDate(Date)したがって、 null以外の値で呼び出された単純な検証のみを実行しましたDate。カスタムマッチャーを作成して、Dateオブジェクトが期待どおりのものであるかどうかを確認できます。これは、クラスのみをテストするためのものProductDaoです。

MaingetCreationDateの戻り値をモックする必要がある方法で単体テストを行う場合は、に戻り値を追加しProductDao#createて、永続化されたオブジェクトを返すようにすることができます。

 public class ProductDao {
     public Product create(Product p){
        p.setCreationDate(new Date());
        dao.create(p);
        return p;
     }
 }

次に、メインクラスでproductDaoのリターンをモックすることができます

  @Test
  public void shouldUseReturnedProductFromDaoToLog() {
       // given
       Product product = mock(Product.class);
       Date creationDate = new Date();

       given(product.getCreationDate()).willReturn(creationDate);
       given(dao.create(any(Product.class)).willReturn(product);

       // when      
       Product createdProduct = main.createProduct();

       // then
       assertThat(createdProduct, is(equalTo(product)));
  }

DAOから返されたものと同じかどうかをテストしたかったので、createProductに戻りを追加しました。ProductDao次に、期待されること(creationDateの設定)を実行するかどうかを確認する単体テストをMain(製品の作成とDaoでの永続化)から分離します。

お役に立てれば。

于 2013-02-21T21:45:04.357 に答える
1
  1. 完全に有効なアプローチは、creationDateが「設定」されているProductのインスタンスを作成し、mockProductDaoにそれを返すことだと思います。

    Date timeStamp = new Date();
    Product productWithCreationDate = new Product();
    productWithCreationDate.setCreationDate(timeStamp);
    when(mockProductDao.create(anyObject()).thenReturn(productWithCreationDate);
    
  2. productDAO.create(p)を呼び出す場所であれば、p次の行の(creationDateを使用して)アクセスできるので、ProductDAOからpを返す必要はないと思います。

  3. pDAOレイヤーを信頼しない場合にのみ、DAOから読み戻す必要があります:)したがって、create()メソッドが失敗した場合にDAOレイヤーが正しい例外をスローすることを確信しているので、再読み込みする必要はないと思います。pまた。

于 2013-02-21T21:39:48.657 に答える
0

Dateセッターを介して作成を割り当てる必要があるのはなぜですか? Dateinコンストラクターを割り当てるだけです:

Product p = new Product();  //here you set creation date
productDAO.create(p);  
于 2013-02-21T21:42:26.893 に答える