2011-05-25 3 views
8

私は現在の時刻に対して日付と時刻の計算を行うコードをいくつか書いています。 Joda時間では、これは不変オブジェクトであるため、(Java)コンストラクタによってアクセスされます。 new DateTime()が特定の定数の瞬間を返すように模擬できるようにする必要がありますので、合理的なテストアサーションを行うことができますが、他のDateTimeメソッドだけを残しておきます。Grailsでは、Jodaの時間を使って現在の時間を模擬する良い方法がありますか?

これは厄介なことを証明しています。 Grails mockFor(DateTime, true)は、Javaコンストラクタを模倣することはできませんが、Joda時間で時間を取得するための明示的または可読な非コンストラクタの方法はありません。

利用可能なオプションは、JMockitやEasyMock 3クラスのような低レベルのJVMテクニックだけで、Grailsの痛みです。これを達成するための簡単な方法がありますか?

答えて

5

テストを実行している場合のみresources.groovyMockTimeServiceを使用しています。ユニットテストでは、

currentTimeは、ユニットテストクラスのフィールドである
domainInstance.dateService = [ now: { currentTime } ] as DateService 

でそれを嘲笑します。これは、誰もがdateService(私たちの唯一の世界的に唯一の依存関係)に依存し、srcクラスの場合、手で渡す必要があります。

単位テスト、OTOHは、それでかなり明確に見えます。

+0

偉大な答え。私は、このテストを可能にするためだけに、システムを異なる方法で構築することを避けたいと思っていたことがありましたが、コンストラクタをモックするのがどれほど苦労しているかについて多くを学んできました。おかげさまで –

+0

私は直接コンストラクタの呼び出しを避けようとします。これは "インタフェース用のコード"に違反します。作成されたインスタンスはテストのように外部化することができず、時には '構築ブロブ 'になります。それで、それは依存性注入の形になった。 –

2

あなたは単に古き良きOO原則を使用することができます。

interface TimeService { 
    DateTime getCurrentTime() 

    // other time-related methods 
    } 

    class JodaTimeService implements TimeService { 
    DateTime getCurrentTime() { 
     new DateTime() 
    } 
    } 

    class MockTimeService implements TimeService { 
    DateTime getCurrentTime() { 
     // return a fixed point in time 
    } 
    } 

あなたのコードは、依存性注入によってTimeServiceの実装への参照を取得する必要があります。私たちは、now()方法でdateServiceを作成することになった

import grails.util.Environment 

beans = {  
    if (Environment.current == Environment.TEST) { 
     timeService(MockTimeService) 

    } else { 
     timeService(JodaTimeService) 
    } 
} 
+0

上記と同じアプローチ、多くのありがたく、そして良い解決策が深いところまで働いています。また、テスト環境を使用してスイッチを切り替える際のヒントについては、おかげさしだします。 –

18

私はこれがすでに受け入れられていることを知っていますが、Joda時間ではあなたが好きなように凍結して設定することができます。だからあなたは時間を凍結し、時間を前にして、後ろ向きに行くことができます。あなたがJodaを一貫して使用している場合、あなたのオブジェクトはあなたが設定した時間どおりに "今"になります。

// Stop time (and set a particular point in time): 
DateTimeUtils.setCurrentMillisFixed(whenever); 

// Advance time by the offset: 
DateTimeUtils.setCurrentMillisOffset(offsetFromCurrent); 

// Restore time (you could do this in an @After method) 
DateTimeUtils.setCurrentMillisSystem(); 
+0

私はこれのようなことを望んでいました。これにより、テストがはるかに簡単になります。素晴らしいヒント! –

+0

今私はジョーダにいるので馬鹿だと感じる。それは良い方法です。良い、私は何かを学んだ。 –