2017-02-06 57 views
2

私はUnitFormのスコープに目的がないので、DateFormatクラスをモックしようとしています。私はorg.mockito.Mockitoライブラリを使用しています。次のコードjunitテストでDateFormatクラスをモックする

import static org.mockito.Mockito.when; 
import static org.mockito.Mockito.any; 
import org.mockito.Mock; 
import org.mockito.MockitoAnnotations; 

import org.junit.Before; 

public class someTest { 

    @Mock 
    DateFormat formatter; 

    @Before 
    public void before() { 
     MockitoAnnotations.initMocks(this); 
     when(formatter.format(any(Date.class))).thenReturn("2017-02-06"); 
    } 
} 

は、次のエラーを与える:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 3 matchers expected, 1 recorded:

-> at someTest.before(someTest.java:33)

This exception may occur if matchers are combined with raw values: //incorrect: someMethod(anyObject(), "raw String"); When using matchers, all arguments have to be provided by matchers. For example: //correct: someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.

at java.text.DateFormat.format(Unknown Source)
at someTest.before(someTest.java:33)

私は正しい方法でDateFormatクラスをモックはどうすればよいですか?あなたが見ることができるように

+0

実際のインスタンスを作成するのは簡単ではないでしょうか? 'Modeler = new SimpleDateFormat(" '2017-02-06' ");' –

+0

@AndyTurner実際のインスタンスをMockedオブジェクトと比較した場合のメリットは何ですか? – henrik

+1

私はその質問をあなたに回します:実際のインスタンスを使用するのではなく、このオブジェクトを嘲笑することによって、あなたは何を得ると思いますか? –

答えて

4

問題がformat(Date date)

public final String format(Date date) { 
    return format(date, new StringBuffer(), 
        DontCareFieldPosition.INSTANCE).toString(); 
} 

の実装であり、それは最終的です。 Mockitoは最終的な方法をモックできません。代わりに、それは実際の方法を呼び出すでしょう。方法format(date)は、あなたが期待通りの結果がなるあなたのモックメソッドを呼び出しますとき、回避策として 、あなたはそうする方法format(date, new StringBuffer(), DontCareFieldPosition.INSTANCE)

when(formatter.format(any(Date.class), any(StringBuffer.class), 
         any(FieldPosition.class))) 
    .thenReturn(new StringBuffer("2017-02-06")); 

を模擬することができます。

+0

エラーの原因を指摘していただきありがとうございます。フレームワークによって提供されるエラーメッセージは少し混乱していました。あなたの提供された回避策は私にはうまくいきます! – henrik

+1

ここで欠落している(または、おそらく、十分にはっきりしない)細かいところは、 'when'呼び出しがデリゲートメソッドを呼び出す実際のメソッドを呼び出すことです。つまり、' when'呼び出しについてmockitoが最初に知っているのはデリゲートメソッドが呼び出されたので、*その*メソッド呼び出しのモックを設定する必要があります。これは、テストコードが 'TextFormat'の実装の詳細に依存していることを意味します - これは[Fragile Base Class problem](https://en.m.wikipedia.org/wiki/)の結果としてテストコードが脆弱になります。 Fragile_base_class)。 –

+0

@AndyTurner TextFormatではなく、DateFormatを意味しますか?そうでなければ私は混乱している:)はい、あなたは正しい、mockitフレームワークの変更は、テストが動作を停止させる可能性がありますが、それは私と一緒にフィンです。更新テストは、実動コードと比較して簡単に管理できます。しかし、良い点、! – henrik

2

Serghey Bishyrで指摘されているように、final methodをモックしようとしていますが、これはMockitoでは実行できません。

モックフレームワークで何かをすることができない場合(最終的な方法を模倣するなど)、別のフレームワーク(Powermockなど)を見つけるか、別の方法で回避する必要があります。 Wikipedia article about mocksから

:上記の点に

In a unit test, mock objects can simulate the behavior of complex, real objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test. If an object has any of the following characteristics, it may be useful to use a mock object in its place:

  • the object supplies non-deterministic results (e.g. the current time or the current temperature);
  • it has states that are difficult to create or reproduce (e.g. a network error);
  • it is slow (e.g. a complete database, which would have to be initialized before the test);
  • it does not yet exist or may change behavior;
  • it would have to include information and methods exclusively for testing purposes (and not for its actual task).

どれもあなたのコードに適用されませんので、モックを使用する必要はありません。 DateFormatの実際の実装を使用することは「非実用的または不可能」ではありません。

代わりの嘲笑DateFormatを供給、SimpleDateFormatを供給:

formatter = new SimpleDateFormat("'2017-02-06'"); 

明らかに問題のコードから、必要に応じて' sがにそれらの間のテキストを引き起こすので、これは常に、任意の入力のための2017-02-06を返します。文字通り取られる。

+0

回避策を提供するために+1を与える! – henrik

0
正解を越えて

、一つの重要な注意事項:

when(formatter.format(any(Date.class)) 

方法は、最終的ではありません場合は、あなただけ

when(formatter.format(any()) 

Mockitoは何が来るのか理解してくれていると行くことができるし、何が外に出るのですか(少なくともJava8を使用している場合)

関連する問題