Я пишу модульный тест для службы, которая обращается к службе API, которая обращается к API Google Calendars.
Служба переносит ответ от API в Observable. Тем не менее, модульное тестирование оказывается чрезвычайно сложным. Я не могу заглушить класс Event
из API Календаря Google. У меня есть следующие реализации:
GoogleCalendarAPIService.kt
open class GoogleCalendarsApiServiceModule constructor(private val googleCredentialsUtilityModule: IGoogleCrdentialsUtilityModule): IGoogleCalendarsApiServiceModule {
private val googleCredential: Credential
private val httpTransport: NetHttpTransport = NetHttpTransport()
private var googleCalendarService: Calendar
init {
this.googleCredential = this.googleCredentialsUtilityModule.getCredentials(this.httpTransport)
this.googleCalendarService = ServiceBuilder().buildGoogleCalendarService(this.googleCredential, this.httpTransport)
}
override fun getCalendarEvents(): List<Event> {
val now = DateTime(System.currentTimeMillis())
val events: Calendar.Events? = googleCalendarService.events()
val allEvents = events!!.list("primary")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute()
return allEvents.items
}
override fun getEventById(eventId: String): Event {
return googleCalendarService.events().get("primary", eventId).execute()
}
}
И затем, конечно, фактический сервис, который вызывает уровень представления: GoogleCalendarService
class GoogleCalendarService(context: Context): IGoogleCalendarService {
private val googleCredentialsUtilityModule: GoogleCredentialsUtilityModule = GoogleCredentialsUtilityModule(context);
private val googleCalendarsApiServiceModule: GoogleCalendarsApiServiceModule = GoogleCalendarsApiServiceModule(googleCredentialsUtilityModule)
override fun getCalendarEvents(): Observable<List<MeetingEvent>> {
val handler: ObservableOnSubscribe<List<Event>> = getObservableHandler { this.googleCalendarsApiServiceModule.getCalendarEvents() }
return Observable.create(handler).map { mapMeetingEvents(it) }
}
override fun getCalendarEventsViaRoomName(roomName: String): Observable<List<MeetingEvent>> {
val handler: ObservableOnSubscribe<List<Event>> = getObservableHandler { this.googleCalendarsApiServiceModule.getCalendarEvents() }
return Observable.create(handler).map { mapMeetingEventsByRoomName(it, roomName) }
}
override fun getEventById(eventId: String): Observable<MeetingEvent> {
val handler: ObservableOnSubscribe<Event> = getObservableHandler { this.googleCalendarsApiServiceModule.getEventById(eventId) }
return Observable.create(handler).map { mapSingleMeetingEvent(it) }
}
}
Просто чтобы получить все, что я пытаюсь сделать, это убедиться, что Observable завершен в моем модульном тесте, и у меня есть следующий код для этого теста:
@RunWith(MockitoJUnitRunner::class)
class GivenASuccessfulRequestToRetrieveAllCalendarEvents {
@Mock
private val mockGoogleCalendarsApiServiceModule: IGoogleCalendarsApiServiceModule = mock(IGoogleCalendarsApiServiceModule::class.java)
@InjectMocks
private var googleCalendarService: IGoogleCalendarService = mock(GoogleCalendarService::class.java)
@Before
fun setup() {
}
@Test
fun thenAnObservableListOfEventsShouldBeReturned() {
doReturn(mockedGoogleCalendarEvents).`when`(this.mockGoogleCalendarsApiServiceModule).getCalendarEvents()
this.googleCalendarService.getCalendarEvents()
.test()
.assertComplete()
}
}
Когда я запускаю тест, я получаю ошибку :
java.lang.NullPointerException
at GivenASuccessfulRequestToRetrieveAllCalendarEvents.thenAnObservableListOfEventsShouldBeReturned(GivenASuccessfulRequestToRetrieveAllCalendarEvents.kt:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Обычно я предполагаю, что это означает, что я неправильно настроил свои макеты, однако всякий раз, когда я отлаживаю, я получаю идентификатор экземпляра каждого макета в отладчике, что означает, что они Я просто чувствую, что мне не хватает крошечной детали.
Любая помощь?