2017-02-22 16 views
3

У меня есть вызов API retrofit2RxJava JUnit тест с Модернизированный бросает NullPointerException

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

У меня есть Repository, который использует этот API, как SO-

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'sgetFeeds() с теми же аргументами, которые используются для вызова 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>>() { ... } 

Что я делаю не так?

ответ

2

Вы используете mock метод FoodRepositoryImpl, который является реальным объектом (с использованием издевательства feedService).

изменение:

feedRepository = FeedRepositoryImpl.getFeedRepository(feedService); 

в

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

EDIT:

Вы просто должны изменить способ издеваться, чтобы (шпионаж FeedRepositoryImpl Не важно):

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

Не могли бы вы объяснить это более подробно? Я попробовал это, но все еще имею то же 'NullPointerException' в' feedService.getFeeds(). ConcatMap() '. –

+0

Несомненно. Вы вызываете 'когда (feedRepository.getFeed (PAGE_NUMBER, КАТЕГОРИИ, ЯЗЫК)). ThenReturn (emptyFeed);', что означает, что вы пытаетесь высмеять метод объекта feedRepository. Mockito не может издеваться над методами на реальных объектах. Mockito может сделать это либо на полностью издевающихся объектах (используя '@ Mock' или' Mockito.mock'), либо обернутые реальные объекты (используя 'Mockito.spy'). –

+0

Единственный объект, который вы издеваетесь, это 'feedService'. Вы создали 'feedRepository' обычным способом (используя посмеянный' feedService'). –

Смежные вопросы