Почему assertValueSet () возвращает ошибку подтверждения, когда списки равны? - PullRequest
0 голосов
/ 17 апреля 2020

Здравствуйте, уважаемое сообщество! Я прошу помощи. Я уже много раз искал ответ на этот вопрос, но не могу его найти.

Я пишу Android приложение с использованием Rx Java. Я борюсь с модульным тестом, потому что следующий код дает мне ошибку подтверждения:

@RunWith(JUnit4.class)
public class MusicRepositoryImplementationTest {
    private MusicRepository musicRepository;
    private ArtistDomainDataMapper artistDomainDataMapper;
    private SongDomainDataMapper songDomainDataMapper;
    @Mock
    private LocalDataSource localDataSource;
    @Mock
    private RemoteDataSource remoteDataSource;


    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        artistDomainDataMapper = new ArtistDomainDataMapper();
        songDomainDataMapper = new SongDomainDataMapper();
        musicRepository = new MusicRepositoryImplementation(
                this.artistDomainDataMapper,
                this.songDomainDataMapper,
                localDataSource,
                remoteDataSource
        );
    }

    @Test
    public void test_getTopArtists_remote_and_local_success() {
        List<ArtistData> artistDataList = Generator.getArtistsDataList();
        List<ArtistEntity> artistEntityList = artistDataList
                .stream()
                .map(it -> artistDomainDataMapper.from(it))
                .collect(Collectors.toList());
        Mockito.when(localDataSource.getTopArtists())
                .thenReturn(Observable.just(artistDataList));
        Mockito.when(remoteDataSource.getTopArtists())
                .thenReturn(Observable.just(artistDataList));

        TestObserver testObserver = musicRepository.getTopArtists().test();

        Mockito.verify(localDataSource, times(1)).getTopArtists();
        testObserver
                .assertSubscribed()
                .awaitCount(1)
                .assertValueSet(artistEntityList)
                .assertComplete()
                .dispose();

    }
}

это дает мне ошибку:

java.lang.AssertionError: Value not in the expected collection: [domain.main.entities.ArtistEntity@193f604a, domain.main.entities.ArtistEntity@20f5239f] (class: ArrayList) (latch = 0, values = 1, errors = 0, completions = 1)

пожалуйста, посмотрите на реализацию:

public class MusicRepositoryImplementation implements MusicRepository {

    private ArtistDomainDataMapper artistDomainDataMapper;
    private SongDomainDataMapper songDomainDataMapper;
    private LocalDataSource localDataSource;
    private RemoteDataSource remoteDataSource;

    @Inject
    public MusicRepositoryImplementation(
            ArtistDomainDataMapper artistDomainDataMapper,
            SongDomainDataMapper songDomainDataMapper,
            LocalDataSource localDataSource,
            RemoteDataSource remoteDataSource
    ) {
        this.artistDomainDataMapper = artistDomainDataMapper;
        this.songDomainDataMapper = songDomainDataMapper;
        this.localDataSource = localDataSource;
        this.remoteDataSource = remoteDataSource;
    }

    @Override
    public Observable<List<ArtistEntity>> getTopArtists() {
        Observable<List<ArtistEntity>> localTopArtistsObservable = localDataSource
                .getTopArtists()
                .flatMapIterable(list -> list)
                .map(item -> artistDomainDataMapper.from(item))
                .toList()
                .toObservable();
        return remoteDataSource.getTopArtists()
                .map(list -> {
                    localDataSource.saveTopArtists(list);
                    return list;
                })
                .flatMapIterable(list -> list)
                .map(item -> artistDomainDataMapper.from(item))
                .toList()
                .toObservable()
                .onErrorResumeNext(localTopArtistsObservable);

    }

код для сопоставителя, который я использую внутри цепочки:

public class ArtistDomainDataMapper implements Mapper<ArtistData, ArtistEntity> {
    @Inject
    public ArtistDomainDataMapper() {
    }

    @Override
    public ArtistEntity from(ArtistData artistData) {
        return new ArtistEntity(
                artistData.getName(),
                artistData.getArtistImageUrl()
        );
    }

Конечно, я пробовал не только basi c AssertValueSet (), но и AssertValue () и использование сравнений массивов в lambda Выражение.

Что еще я могу добавить, так это аналогичный тест, который я написал для другого слоя, и он проходит. Интересно, может ли это быть вызвано тем, что используется инъекция планировщика и все тестируемое вызывается в Schedulers.trampoline (), но я попытался использовать в тесте метод subscribeOn (Schedulers.trampoline ()) для getTopArtists (), но это не так. работать тоже. Пожалуйста, посмотрите на рабочий:

@RunWith(MockitoJUnitRunner.class)
public class getTopArtistsTaskTest {
    private GetTopArtistsTask getTopArtistsTask;
    Void avoid;
    @Mock
    private MusicRepository musicRepository;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        getTopArtistsTask = new GetTopArtistsTask(musicRepository, Schedulers.trampoline(), Schedulers.trampoline());

    }

    @Test
    public void test_getTopArtists_success() {
        List<ArtistEntity> artistsList = Generator.getArtistsEntitiesList();
        Mockito.when(musicRepository.getTopArtists()).thenReturn(Observable.just(artistsList));
        TestObserver testObserver = getTopArtistsTask.buildUseCase(avoid).test();

        Mockito.verify(musicRepository, times(1)).getTopArtists();
        testObserver.assertSubscribed()
                .assertValue(artistsList)
                .assertComplete()
                .dispose();
    }

Реализация выглядит следующим образом:

public class GetTopArtistsTask extends ObservableUseCase<List<ArtistEntity>, Void> {

    private MusicRepository musicRepository;

    @Inject
    public GetTopArtistsTask(MusicRepository musicRepository, Scheduler foregroundScheduler, Scheduler backgroundScheduler) {
        super(foregroundScheduler, backgroundScheduler);
        this.musicRepository = musicRepository;
    }

    @Override
    protected Observable<List<ArtistEntity>> generateObservable(Void aVoid) {
        return this.musicRepository.getTopArtists();
    }
}

public abstract class ObservableUseCase<Return, Input> {

    private Scheduler foregroundScheduler;
    private Scheduler backgroundScheduler;

    public ObservableUseCase(Scheduler foregroundScheduler, Scheduler backgroundScheduler) {
        this.foregroundScheduler = foregroundScheduler;
        this.backgroundScheduler = backgroundScheduler;
    }

    protected abstract Observable<Return> generateObservable(Input input);

    public Observable<Return> buildUseCase(Input input){
        return generateObservable(input)
                .subscribeOn(backgroundScheduler)
                .observeOn(foregroundScheduler);
    }
}

Если что-то не так с вопросом, пожалуйста, поправьте меня. Просьба о помощи:)

...