2016-12-07 69 views
1

我有一个工具测试问题,它检查在其中一种方法中将其状态保存为共享首选项的活动。经测试的代码如下所示:使用Mockito和Dagger的SharedPreferences

initialPresenter.getLocalData().edit() 
        .putString("SessionDetails", new Gson().toJson(sessionData)) 
        .putBoolean("relog", false) 
        .apply(); 

LocalData通过dagger2注入演示者。我已经为它创建了模拟,并且我正在补充它们,所以在那里一切正常。例如。

when(localData.getBoolean("signed_using_email", false)).thenReturn(true); 

当我试图以某种方式禁用或忽略编辑数据时会出现问题。我创造了另一个模拟;这次的编辑器,所以当SharedPref调用编辑它显式模拟;

@Mock SharedPreferences.Editor mEditor; 
. 
. 
. 
when(localData.edit()).thenReturn(mEditor); 

但后来我得到错误:

Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'android.content.SharedPreferences$Editor android.content.SharedPreferences$Editor.putBoolean(java.lang.String, boolean)' on a null object reference 

其中顺便说一句。怪吓人怪异,为什么putBoolean没有putString?它看起来像第一个模拟工程很好,但它然后嵌套(?)并抛出错误。

也尝试了另一种方法,而不是桩/替换答案我用过没有;

doNothing().when(localData).edit(); 

但它也造成了类似的问题抛出错误:

org.mockito.exceptions.base.MockitoException: 
Only void methods can doNothing()! 
Example of correct use of doNothing(): 
doNothing(). 
doThrow(new RuntimeException()) 
.when(mock).someVoidMethod(); 
Above means: 
someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called 

任何想法如何解决呢?我不需要保存任何状态,以后我可以嘲笑它,这很好,因为我会通过编写这些测试来获得文档。早些时候,我使用PowerMockito来压缩使用sharedPreferences的整个方法,但是这个解决方案似乎并不好。

+1

你的问题本质上是如何模拟'SharedPreferences.Editor'的'builder'语法。查看[Jeff Bowman的回答](https://stackoverflow.com/questions/8501920/how-to-mock-a-builder-with-mockito)了解如何使用Mockito完成此操作。换句话说,尝试'@Mock(answer = RETURNS_SELF)SharedPreferences.Editor mEditor;' –

+0

@DavidRawson谢谢!我已经改变了创建模拟为 mEditor = mock(SharedPreferences.Editor.class,RETURNS_DEEP_STUBS); 它似乎工作。你能发表你的评论作为答案,所以我可以接受它吗? :) – Kamajabu

回答

2

这里的问题是,SharedPreferences.Editor有一个“构建器”语法,其中每个调用putString(),putBoolean()等返回Editor

当你模拟这个对象时,你想通过每次调用这些方法之一时模拟自身返回来模仿这种行为。

Jeff Bowman's answer上嘲讽建设者语法用的Mockito,你可以在你的代码如下变化做到这一点:

@Mock(answer = RETURNS_SELF) SharedPreferences.Editor mEditor; 

或者,你可能只是想利用RETURNS_DEEP_STUBS

mEditor = mock(SharedPreferences.Editor.class, RETURNS_DEEP_STUBS);