Android Studio 2.1.2
我正在尝试测试调用getJsonFromResource
的{{1}}。
我希望能够测试2个案例1 loadNewsFeed
将返回一个空字符串,另一个将返回一些json字符串。
所以我试图模拟loadNewsFeed
函数返回一个空字符串。但是,当调用具体loadNewsFeed
时,它将调用实际getJsonFromResource
并导致空指针异常。
这是我在测试评论中尝试解释我正在做的事情:
loadNewsFeed
这是我要测试的课程。
@Test
public void shouldFailIfJSONStringIsEmpty() throws Exception {
/* Mock Context class */
Context context = mock(Context.class);
/* initialize the concrete parseNewsFeed passing in the fake context */
ParseNewsFeed parseNewsFeed = new ParseNewsFeed(context);
/* Create a mock of the parseNewsFeed so a fake call to loadNewsFeed will return an empty string */
ParseNewsFeed mockParseNewsFeed = mock(ParseNewsFeed.class);
/* Mock the events that will be verified */
ParseNewsFeedContract.Events<Status> mockEvents = mock(ParseNewsFeedContract.Events.class);
/* Return an empty string when loadNewsFeed is called */
when(mockParseNewsFeed.loadNewsFeed()).thenReturn("");
/* Called the concrete getJsonFromResource */
parseNewsFeed.getJsonFromResource(mockEvents);
/* verify that onNewsFailure was called once and onNewsSuccess was never called */
verify(mockEvents, times(1)).onNewsFailure(anyString());
verify(mockEvents, never()).onNewsSuccess(any(Status.class));
}
答案 0 :(得分:5)
首先,您的原始代码无法正常工作的原因是因为您的两个对象parseNewsFeed
和mockParseNewsFeed
之间没有任何关系,因此您做的存根mockParseNewsFeed
调用parseNewsFeed.getJsonFromResource(mockEvents)
时没有任何效果。使用大卫华莱士建议的spy
会有效,但如果我是你,我会稍微改写代码,以便更容易测试。
一个观察结果是,loadNewsFeed()
方法中的代码似乎与ParseNewsFeed
类没有很强的关系,因此我将此代码提取到对象中(例如NewsFeedLoader
),然后将此对象作为ParseNewsFeed
类的依赖项。然后,您可以轻松地模拟此Loader
(返回""
或在传递Context
时可能需要的任何字符串,也可能是R.raw.news_list
ID。使用此Loader
类,您甚至可以单独对ParseNewsFeed
进行单元测试,并且可以根据需要改进Loader
(例如,更好的方式来读取原始资源)而不影响ParseNewsFeed
类。
答案 1 :(得分:3)
看起来你想要一个ParseNewsFeed
对象,其中loadNewsFeed
方法已被存根,但其他方法正常工作。最简单的方法是创建一个间谍,比如
ParseNewsFeed spyParseNewsFeed = Mockito.spy(new ParseNewsFeed(context));
Mockito.doReturn("").when(spyParseNewsFeed).loadNewsFeed();
答案 2 :(得分:3)
使用模拟上下文的when()
和then()
方法。它实际上是在official tutorial here.
@Mock
Context mMockContext;
@Test
public void readStringFromContext_LocalizedString() {
// Given a mocked Context injected into the object under test...
when(mMockContext.getString(R.string.hello_word))
.thenReturn(FAKE_STRING);
ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
// ...when the string is returned from the object under test...
String result = myObjectUnderTest.getHelloWorldString();
// ...then the result should be the expected one.
assertThat(result, is(FAKE_STRING));