2017-05-18 10 views
2

がAndroidAnnotationsのSharedPreferencesに呼び出すモックチェーン方法は、私は<a href="https://github.com/androidannotations/androidannotations/wiki/SharedPreferencesHelpers" rel="nofollow noreferrer">SharedPreferences</a>を生成する<a href="http://androidannotations.org/" rel="nofollow noreferrer">AndroidAnnotations</a>を使用していたプロジェクトで

preferences.enabled().get(); 
preferences.enabled().put(true); 

私が記述しようとしていますいくつかの論理をチェックする単体テスト。そこ私は好みをモックとしたい:

@Mock MyPreferences_ prefs; 
MyLogic logic; 

@Before 
public void setUp() { 
    MockitoAnnotations.initMocks(this); 
    logic = new Logic(); 
} 

@Test 
public void testEnabled() throws Exception { 
    when(prefs.enabled().get()).thenReturn(false); 
    assertThat(logic.isEnabled()).isEqualTo(false); 
} 

しかし、アクセスprefs.enabled()スローNullPointerException

java.lang.NullPointerException at com.example.MyLogicTest.isValuesStoredProperly(MyLogicTest.java) ...

それはMockitoと(nullのオブジェクトを含む)の連鎖メソッド呼び出しを模擬することは可能ですか?

更新

helpful suggestions by alayorに基づいて更新として、次のように私は私の実装を変更:

public class MyLogicTest { 

    @Mock SharedPreferences  prefs; 
    @Mock CustomSharedPreferences_ prefs_; 

    MyLogic logic; 

    @Before 
    public void setUp() { 
     MockitoAnnotations.initMocks(this); 
     logic = new MyLogic(); 
    } 

    @Test 
    public void testEnabled() throws Exception { 
     MockPrefs mockPrefs = new MockPrefs(prefs); 
     when(prefs_.enabled()).thenReturn(mockPrefs.getEnabledPrefField()); 
     doNothing().when(prefs_.enabled()).put(anyBoolean()); // <-- fails 
     when(prefs_.enabled().get()).thenReturn(false); 
     assertThat(logic.isEnabled()).isEqualTo(false); 
    } 

    private class MockPrefs extends SharedPreferencesHelper { 

     public MockPrefs(SharedPreferences sharedPreferences) { 
      super(sharedPreferences); 
     } 

     public BooleanPrefField getEnabledPrefField() { 
      return super.booleanField("enabled", enabledOld); 
     } 

    } 
} 

これはまだはここを失敗:

doNothing().when(prefs_.enabled()).put(anyBoolean()); 

prefs_.enabled()からBooleanPrefFieldオブジェクトがありますfinalと嘲笑することはできません。

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at MyLogicTest.testEnabled 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, which is not supported 
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed 

サンプルプロジェクト

ソリューション

  • 上記のサンプルプロジェクトで作業を見つけてください。
+0

'prefs.enabled()'は何を返しますか? – alayor

答えて

1

あなたはMyPreferences_

@Mock(answer = Answers.RETURNS_DEEP_STUBS)でこの注釈を使用することができます呼び出します。

しかし、代わりにprefs.enabled()を呼び出した結果を嘲笑することをお勧めします。

@Mock 
BooleanPrefField booleanPrefField; 

@Test 
public void testEnabled() throws Exception { 
    when(prefs.enabled()).thenReturn(booleanPrefField); 
    when(booleanPrefField.get()).thenReturn(false); 
    assertThat(logic.isEnabled()).isEqualTo(false); 
} 

注:prefs.enabled()戻り、そのオブジェクトの種類とMyObjectに置き換えてください。この方法を使用すると、メソッド呼び出しの動作をより詳細に制御できます。

更新:BooleanPrefFieldが最終の場合は、そのクラスのオブジェクトを単純に返信することができます。

when(prefs.enabled()).thenReturn(SharedPreferencesHelper.booleanField("", false)); 
+0

私はそれを試みましたが、 'BooleanPrefField'は' final'です。エラー: 'org.androidannotations.api.sharedpreferences.BooleanPrefFieldクラスをモック/スパイすることはできません。なぜなら、Mockitoは偽装することができません:final class' – JJD

+0

私は自分の答えを更新しました。 – alayor

+0

そして、 'BooleanPrefField'は、' new BooleanPrefField(true) 'のような新しいオブジェクトのインスタンス化を防ぐパッケージプライベートです。 – JJD

0

MockitoAnnotationsの代わりに@RunWith(MockitoJUnitRunner.class)でテストを実行しましたか?ランナーは、すべての@Mock注釈付きフィールドを自動的に初期化し、そのNPEを取り除く必要があります。

また、answerの後にお手伝いできます。チェーン方法を模擬するために

+0

'prefs'オブジェクトが初期化されます。それは問題ではありません。 NPEは、実装のケースで 'BooleanPrefField'を返す' prefs.enabled() 'で' .get'を呼び出すと発生します。 – JJD

関連する問題

 関連する問題