使用mockito来测试使用上下文的函数

时间:2016-08-03 03:50:28

标签: android mockito

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));
}

3 个答案:

答案 0 :(得分:5)

首先,您的原始代码无法正常工作的原因是因为您的两个对象parseNewsFeedmockParseNewsFeed之间没有任何关系,因此您做的存根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));