Я пытаюсь использовать Robolectric для тестирования своего приложения для Android, но столкнулся с проблемой тестирования, которую я не могу понять.
Я тестирую Activity, который расширяет мой класс BaseActivity и использует RxAndroid, этот класс выглядит так:
public abstract class BaseActivity extends AppCompatActivity {
protected final SharedService sharedService = MyApplication.getInstance().getSharedService();
protected Activity getActivity() {
return this;
}
}
Как видите, он получает объект sharedService из моего базового класса Application.
Затем в своей деятельности я ссылаюсь на этот код следующим образом:
//...
Subscription s = sharedService.login(params)
.compose(ObservableUtils.<JsonObject>applySchedulers())
.subscribe(new Action1<JsonObject>() {
@Override
public void call(JsonObject jsonObject) {
//...
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
//...
}
});
subscriptions.add(s);
//..
Таким образом, Activity напрямую ссылается на переменную sharedService из BaseActivity для доступа к ней и вызова метода объекта SharedService. Он использует RxAndroid для получения наблюдаемого.
Код в вызове Retrofit выглядит следующим образом:
@POST("/login")
Observable<JsonObject> login(
@Body JsonObject body) ;
Проблема в том, что когда я прихожу для тестирования с помощью Robolectric, я получаю исключение с нулевым указателем в Activity, когда вызывается код RxAndroid.
Мой тест выглядит следующим образом:
@Config(constants = BuildConfig.class)
@RunWith(TestRunner.class)
public class MyActivityTest{
@Mock
private SharedService mockSharedService;
@Before
public void setup() {
// Convenience method to run Activity through the Activity Lifecycle methods:
// onCreate(...) => onStart() => onPostCreate(...) => onResume()
MockitoAnnotations.initMocks(this);
TestMyApplication testMyApp = (TestMyApplication) TestCompanionApplication.getInstance();
testMyApp.setSharedService(this.mockSharedService); //Set our Mocked application class to use our mocked API
//Build our activity using Robolectric
ActivityController<MyActivity> controller = Robolectric.buildActivity(MyActivity.class);
activity = controller.get();
controller.create(); //Create out Activity
//..Get views
}
@Test
public void testService(){
btnTest.click(); //This fires the service call
Mockito.verify(this.mockSharedService).login((JsonObject) Mockito.any());
}
Когда я запускаю этот тест, я получаю исключение NullPointerException.
Итак, я знаю, что мне каким-то образом нужно заставить Activity использовать фиктивный API, который я установил для класса TestMyApplication, но поскольку BaseActivity создает переменную, которая содержит это, а затем другие мои действия ссылаются на это, как мне сделать это с помощью Robolectric?
1 ответ
Исправить довольно просто:
when(mockSharedService.login(any())).thenReturn(Observable.just(new JsonObject()));
Но, вероятно, он потерпит неудачу позже, когда вы попытаетесь обработать полученный json
.
null
, когда вы начинаете связывать подписку. Это вызывает NPE. Я заглушил этот вызов, поэтому он возвращает Observable
, который выдаст один JsonObject
при подписке
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.
JsonObject
, а не с POJO? В этом прелесть дооснащения .