Модульный тест с методом LiveData getMainLooper в android.os.
Я не могу заставить работать liveData.postValue при попытке выполнить модульный тест. Я проверял в Google для решения, и это код, который я сейчас имею.
public class ProjectListViewModelTest {
GetProjectList getProjectList = Mockito.mock(GetProjectList.class);
ProjectModel.Project project = new ProjectModel.Project("testing",
"this is a test",
"https://logo.jpg",
new ProjectModel.Company("cat"),
"20150404",
"active");
List<ProjectModel.Project> projects = Arrays.asList(project);
ProjectModel.ProjectList projectsList = new ProjectModel.ProjectList(projects);
ProjectsListViewModel projectsListViewModel;
private PublishSubject<ProjectModel.ProjectList> projectsListPublishSubject = PublishSubject.create();
@Rule public InstantTaskExecutorRule instantExecutorRule = new InstantTaskExecutorRule();
@BeforeClass
public static void setUpRxSchedulers() {
Scheduler immediate = new Scheduler() {
@Override
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
return super.scheduleDirect(run, 0, unit);
}
@Override
public Scheduler.Worker createWorker() {
return new ExecutorScheduler.ExecutorWorker(Runnable::run);
}
};
RxJavaPlugins.setInitIoSchedulerHandler(scheduler -> immediate);
RxJavaPlugins.setInitComputationSchedulerHandler(scheduler -> immediate);
RxJavaPlugins.setInitNewThreadSchedulerHandler(scheduler -> immediate);
RxJavaPlugins.setInitSingleSchedulerHandler(scheduler -> immediate);
RxAndroidPlugins.setInitMainThreadSchedulerHandler(scheduler -> immediate);
}
@Before
@Throws(exceptionClasses = Exception.class)
public void setUp() {
MockitoAnnotations.initMocks(this);
projectsListViewModel = new ProjectsListViewModel(getProjectList);
when(getProjectList.execute()).thenReturn(projectsListPublishSubject.take(1).singleOrError());
}
@Test
public void testExecuteGetProjectsListSuccess() {
LiveData<List<ProjectModel.MapProject>> liveData = projectsListViewModel.getLiveData();
ProjectModel.MapProject expectedResult = new ProjectModel.MapProject(
"testing", "this is a test", "https://logo.jpg",
"cat", "2015-04-04", "active");
projectsListViewModel.getProjects();
projectsListPublishSubject.onNext(projectsList);
Assert.assertEquals(expectedResult, liveData.getValue().get(0));
}
@After
public void tearDownClass(){
RxAndroidPlugins.reset();
}
Код, который я имею в setUpRxSchedulers
является обязательным, чтобы избежать той же ошибки (Method getMainLooper in android.os.Looper not mocked
) с Rx. Но я не могу решить эту ошибку, которая появляется при вызове liveData.post(projectList). На всех форумах, которые я проверял, говорят, что с @Rule public InstantTaskExecutorRule instantExecutorRule = new InstantTaskExecutorRule();
проблема должна быть решена. Но это не мой случай.
Я также поместил здесь модель представления на случай, если она может помочь:
public class ProjectsListViewModel extends ViewModel {
GetProjectList getProjectList;
MutableLiveData<List<ProjectModel.MapProject>> liveData = new MutableLiveData<>();
public ProjectsListViewModel(GetProjectList getProjectList){
this.getProjectList = getProjectList;
}
public LiveData<List<ProjectModel.MapProject>> getLiveData(){
return liveData;
}
public void getProjects(){
getProjectList.execute()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(ProjectModel.ProjectList::getProjects)
.toObservable().flatMapIterable(projects -> projects)
.map(project -> project.convertToMapProject()).toList()
.subscribe(projectsList ->
liveData.setValue(projectsList));
}
}
0 ответов
Использование
InstantTaskExecutorRule
действительно решит это.
Я думаю, проблема в том, что в JUnit 5
@Rule
аннотации, похоже, больше не поддерживаются (так как расширения теперь подходят). Код будет успешно скомпилирован, но правило просто не будет применяться.
Для этого есть (как минимум) два решения:
Используйте JUnit 4
Определенно быстрее, может быть, не лучшим в зависимости от того, сколько вам нужно JUnit 5.
Это можно сделать, просто изменив аннотацию вашего
setup
метод от
@BeforeEach
к
@Before
и путем импорта
@Test
аннотация из JUnit 4. Вот как должен выглядеть ваш импорт.
import org.junit.Before
import org.junit.Rule
import org.junit.Test
Реализовать
InstantTaskExecutorExtension
Это лучше, если вы заботитесь об использовании JUnit 5:)
Вот статья, в которой рассказывается, как точно реализовать
InstantTaskExecutorExtension
. Как только это будет сделано, не забудьте применить его к вашему тестовому классу, используя
@ExtendWith(InstantTaskExecutorExtension::class)
аннотация вместо
@Rule
!