2016-11-30 7 views
0

私はYearMonth.classをmockitoでモックしようとしています。Java 8でYearMonthを擬似する方法

私はgetYeargetMonthのメソッドを呼び出すので、テスト中のメソッドでどの値が使用されているかを制御したいと思います。しかし、私は次の問題を抱いています。

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class java.time.YearMonth 
Mockito cannot mock/spy following: 
    - final classes 
    - anonymous classes 
    - primitive types 
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl$1.withBefores(JUnit45AndHigherRunnerImpl.java:27) 
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:246) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) 
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

テストは、私はテストが持っているよモック

YearMonth yearMonthMock = mock(YearMonth.class); 

のための次の定義と方法を持っている私が仕事を続けるために、例外を解決するにはどうすればよい

YearMonth yearMonth = YearMonth.now(ZoneId.of("UTC")); 
String year = Integer.toString(yearMonth.getYear()); 
String month = Integer.toString(yearMonth.getMonthValue()); 

を次YearMonth.classまたは別のアプローチを使用する必要があります。

+3

?なぜあなたはそれを嘲笑する必要がありますか? –

+1

あなたは何を試そうとしていますか? 'yearMonth.getYear()'が特定の年を返すようにしたい場合、あなたはいつでもそれを直接嘲笑せずに使うことができます - 'YearMonth yearMonth = YearMonth.of(2016,11);' –

答えて

3

静的メソッドによる特定の日付機能へのアクセスは難しいです。システムクロックに依存する静的メソッドをモックしようとしています。これは、いくつかの抜本的な対策を講じることなく、模擬/スパイするのを困難にします。 (システムの時間を変更するなど)

これを回避する方法の1つは、制御できるインターフェイスの背後にあるその機能へのアクセスを抽象化することです。生産の

public interface YearMonthProvider { 
    YearMonth now(ZoneId zone); 
} 

実装は結石ではなく、抽象化に依存するテスト中のこの

public class SystemYearMonth implements YearMonthProvider { 
    public YearMonth now(ZoneId zone) { 
     return YearMonth.now(zone); 
    } 
} 

方法のようになります。柔軟性がスワップアウトするためにこれは今できます

public class MyClass { 
    private YearMonthProvider clock; 

    public MyClass(YearMonthProvider clock) { 
     this.clock = clock; 
    } 

    public void MyMethod(){ 
     //...other code 

     YearMonth yearMonth = clock.now(ZoneId.of("UTC")); 
     String year = Integer.toString(yearMonth.getYear()); 
     String month = Integer.toString(yearMonth.getMonthValue()); 

     //... other code 
    } 
} 

依存関係は必要に応じてテストあなたが直接YEARMONTHを使用することはできませんなぜ

//Arrange 
YearMonth yearMonthStub = YearMonth.of(2016,11); 
YearMonthProvider yearMonthMock = mock(YearMonthProvider.class); 
when(yearMonthMock.now(ZoneId.of("UTC"))).thenReturn(yearMonthStub); 

MyClass sut = new MyClass(yearMonthMock); 

//Act 
sut.MyMethod(); 

//Assert 
//... 
関連する問題