android - 使用 Retrofit 的 RxJava JUnit 测试抛出 NullPointerException

标签 android unit-testing junit retrofit2 rx-java2

我有一个 retrofit2 API 调用

public interface FeedService {
    @GET("/api/v1/feeds")
    Observable<FeedResponse> getFeeds(@Query("page") Integer pageNumber,
                                          @Query("cats") String categories,
                                          @Query("lang") String language);
}

我有一个像这样使用这个 API 的存储库-

public class FeedRepositoryImpl implements FeedRepository {
    private static FeedRepositoryImpl INSTANCE;
    private int FIRST_PAGE = 1;
    private FeedService feedService;

    public static FeedRepositoryImpl getFeedRepository(FeedService feedService) {
        if (INSTANCE == null) {
            INSTANCE = new FeedRepositoryImpl(feedService);
        }
        return INSTANCE;
    }

    @Override
    public Observable<Feed> getFeeds(final int pageNumber, final String categories, final String
            language) {
        return feedService.getFeeds(pageNumber, categories, language)
                .concatMap(new Function<FeedResponse, ObservableSource<? extends Feed>>() {
                    @Override
                    public ObservableSource<? extends Feed> apply(FeedResponse feedResponse) throws
                            Exception {
                        return Observable.fromIterable(feedResponse.feedsData());
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }
}

现在,我正在尝试编写 JUnit 测试,以验证调用 FeedService 的 getFeeds() 时使用的参数与调用 FeedRepository 的参数相同。 getFeeds().

但是,我得到了一个NullPointerException。这是我的测试的样子 -

public class FeedRepositoryImplTest {

    private static String CATEGORIES = "feeds?page=1&cats=top,yt,world,ent,ls,sp";
    private static String LANGUAGE = "lang=en";
    private static int PAGE_NUMBER = 1;

    @Rule
    public ImmediateSchedulersRule immediateSchedulersRule = new ImmediateSchedulersRule();
    @Mock
    FeedService feedService;
    FeedRepositoryImpl feedRepository;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        feedRepository = FeedRepositoryImpl.getFeedRepository(feedService);
    }

    @Test
    public void getFeeds() throws Exception {
        // arrange
        Observable<Feed> emptyFeed = Observable.empty();
        when(feedRepository.getFeed(PAGE_NUMBER, CATEGORIES, LANGUAGE))
                .thenReturn(emptyFeed);

        // act
        feedRepository.getFeed(PAGE_NUMBER, CATEGORIES, LANGUAGE);

        System.out.println("feedRepository.getFeeds(PAGE_NUMBER, CATEGORIES, LANGUAGE)");
        // assert
        verify(feedService).getFeeds(PAGE_NUMBER, CATEGORIES, LANGUAGE);
    }
}

我的 TestRule 看起来像这样 -

public class ImmediateSchedulersRule implements TestRule {
    @Override
    public Statement apply(final Statement base, Description description) {
        return () -> {
                RxJavaPlugins.setIoSchedulerHandler((scheduler) -> {
                        return Schedulers.trampoline();
                });
                RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> {
                        return Schedulers.trampoline();
                });
                RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> {
                        return Schedulers.trampoline();
                });
                RxAndroidPlugins.setMainThreadSchedulerHandler((scheduler) -> {
                        return Schedulers.trampoline();
                });
                RxAndroidPlugins.setInitMainThreadSchedulerHandler((schedulerCallable) -> {
                        return Schedulers.trampoline();
                });
                base.evaluate();
        };
    }
}

在这一行抛出异常 -

.concatMap(new Function<FeedResponse, ObservableSource<? extends Feed>>() { ... }

我做错了什么?

最佳答案

您正在尝试模拟 FoodRepositoryImpl 的方法,它是一个真实的对象(使用模拟的feedService)。

改变:

feedRepository = FeedRepositoryImpl.getFeedRepository(feedService);

feedRepository = Mockito.spy(FeedRepositoryImpl.getFeedRepository(feedService));

编辑:

您应该将 mock 方法更改为(监视 FeedRepositoryImpl 无关紧要):

when(feedService.getFeeds(PAGE_NUMBER, CATEGORIES, LANGUAGE)).thenReturn(emptyFeed);

关于android - 使用 Retrofit 的 RxJava JUnit 测试抛出 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42384343/

相关文章:

javascript - 在 React JS 中使用 Jest 修复单元测试错误

java - mockito 的学习资源

java - 如何编写并发单元测试

java - 与 Junit 并行运行测试

android - 我的应用程序扩展是否会在我的 android 服务之前创建?

android如何通过代码设置手机闹钟

android - Google端点方法不断返回 "name must not be empty"异常

javascript - 如何在 jasmine 中抽象和重用 describe() block ?

java - 如何向数据库中插入百万条数据

android - Sentry 的 Gradle 任务未编译