在AndroidAnnotations SharedPreferences

时间:2017-05-18 14:24:34

标签: java android unit-testing mockito android-annotations

在项目中,我使用AndroidAnnotations生成SharedPreferences

import org.androidannotations.annotations.sharedpreferences.DefaultBoolean;
import org.androidannotations.annotations.sharedpreferences.SharedPref;

@SharedPref(value = SharedPref.Scope.UNIQUE)
public interface MySharedPreferences {

    @DefaultBoolean(false)
    boolean enabled();
}

生成的类可以按如下方式使用:

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模拟链式方法调用(包括空对象)?

更新

作为基于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());

来自BooleanPrefField的{​​{1}}对象为prefs_.enabled(),无法嘲笑。

final

示例项目

解决方案

  • 请在上面的示例项目中找到工作。

2 个答案:

答案 0 :(得分: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);
}

注意:您应该将MyObject替换为prefs.enabled()返回的对象类型。使用这种方式,您可以更好地控制方法调用的行为。

更新:如果BooleanPrefField是最终版,您可以在模拟中返回该类的对象。

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

答案 1 :(得分:0)

您是否尝试使用@RunWith(MockitoJUnitRunner.class)代替MockitoAnnotations来运行测试?跑步者应该自动初始化所​​有@Mock注释字段并摆脱该NPE。

也许跟着answer可以帮助你。