I cannot make liveData.postValue working in while trying to make unit test. I have been checking in google for a solution and this is the code I have now.
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();
}
The code that I have in setUpRxSchedulers
is mandatory in order to avoid the same error (Method getMainLooper in android.os.Looper not mocked
) with Rx. But I cannot solve this error that I get when calling liveData.post(projectList). In all the forums that I checked they say that with @Rule public InstantTaskExecutorRule instantExecutorRule = new InstantTaskExecutorRule();
the problem should be solved. But is not my case.
I put here the viewmodel as well in case it can help:
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));
}
}
The usage of InstantTaskExecutorRule
will actually solve this.
I think the issue is that in JUnit 5 the @Rule
annotation doesn't seem to be supported anymore (as Extensions are now the way to go). The code will compile successfully, but the rule just won't be applied.
Is definitely the quicker, may not be the best depending on how much you need JUnit 5.
This can be done just by changing the annotation of your setup
method from @BeforeEach
to @Before
and by importing the @Test
annotation from JUnit 4.
Here's how your imports should look like.
import org.junit.Before
import org.junit.Rule
import org.junit.Test
InstantTaskExecutorExtension
This is better if you care about using JUnit 5 :)
Here's an article that talks about how to implement precisely InstantTaskExecutorExtension
.
Once that's done remember to apply it to your test class using the @ExtendWith(InstantTaskExecutorExtension::class)
annotation instead of @Rule
!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With