Intereting Posts
rx.Scheduler не может быть предоставлен без @ Provides- или @ Produces-аннотированного метода Котлинская последовательность «пропускает» первые N записей Как создать запрос hql с левым соединением, используя поле из расширяющегося объекта как закрыть kotlin coroutines максимальный параллелизм Как я могу использовать метод (String) Java String непосредственно из источника Kotlin? Как экземпляр объекта в Котлине? Kotlin: исключить null из списка (или другого функционального преобразования) При использовании setcontentview в BottomsheetDialog возникает ошибка, например: «ни одна из следующих функций не может быть вызвана с предоставленными аргументами» Ошибка стекирования потока при использовании факториала рекурсией на ктолине Является ли «org.jetbrains.anko: anko-commons: $ anko_version» неправильным? Какова политика совместимости Котлина? Android Kotlin onItemSelectedListener для неработающего счетчика Как получить последнее значение, исходящее из наблюдаемого Как я могу сделать kotlin реализовать эту функцию сравнения BST хвост рекурсивный? Android Room – простой запрос выбора – не удается получить доступ к базе данных в основной теме

Реактор switchifempty не ведет себя так, как ожидалось, в тесте junit

Я пишу тесты для метода ниже. `

class ScrapedRecipeCache @Autowired constructor(private val cache: RecipeScrapingCacheService, private val recipeService: RecipeService) : ScrapedRecipeProvider { override fun provide(request: ScrapingRequest): Flux<ScrapedRecipe> = cache.retrieve(request.link) .doOnNext { println(it) } .flatMap { (link, _, recipeHash, error) -> recipeService.findByHash(recipeHash) .map { ScrapedRecipe(it, link, error)} .switchIfEmpty(cache.remove(request.link).then(Mono.empty())) } .flux() } 

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

 private val recipeFetched = Recipe("Tortellini", RecipeDifficulty.EASY, 15.0) val cacheContents = RecipeScrapingResource("www.google.com", ScrapingOrigin.JAMIE_OLIVER, recipeFetched.hash, mutableListOf( pl.goolash.core.Exception("aa", ErrorType.WARNING, LocalDateTime.MIN) )) val request = ScrapingRequest("www.google.com", ScrapingOrigin.JAMIE_OLIVER, 4) @BeforeEach fun setUp() { given(cache.retrieve("www.google.com")).willReturn(Mono.just(cacheContents)) given(recipeService.findByHash(recipeFetched.hash)).willReturn(Mono.just(recipeFetched)) } @Test @DisplayName("Then return data fetched from service and don't delete cache") fun test() { cacheFacade.provide(request) .test() .expectNext(ScrapedRecipe(recipeFetched, "www.google.com", cacheContents.error!!)) .expectComplete() .verify() BDDMockito.verify(cache, BDDMockito.never()).remove(request.link) } 

Тест завершился неудачно, так как вызывается cache.remove (request.link). По моему пониманию (или из того, что мне удалось собрать из документации) switchIfEmpty, нужно запускать только в том случае, если recipeService.findByHash возвращает Mono.empty (). Однако отладчик показывает, что он возвращает издеваемое значение Mono.just (fetchedRecipe).

Интересно, что когда я заменяю

 .switchIfEmpty(cache.remove(request.link).then(Mono.empty())) 

с

 .switchIfEmpty(Mono.just(1).doOnNext{println("weeee")}.then(Mono.empty())) 

Затем weee не печатается, поэтому он ведет себя так, как ожидалось, то есть switchIfEmpty не запускается.

Кроме того, проверенная проблема работает правильно в тесте интеграции и не очищает кеш.

Версия для реакторов: 3.1.0-RC1 Другие примечательные детали: Spring Boot 2.0.0-M4, Mockito-core: 2.10, junit 5, проект написан в kotlin

Вопрос в том, кто-нибудь видит в этом что-то неправильное? Потому что я провел два дня и до сих пор не знаю, почему так ведет себя так.

    Наконец, я узнал, как сделать эту работу.

    Чтобы исправить это:

      override fun provide(request: ScrapingRequest): Flux<ScrapedRecipe> = cache.retrieve(request.link) .flatMap { (link, _, recipeHash, error) -> recipeService.findByHash(recipeHash) .map { ScrapedRecipe(it, link, error) } .switchIfEmpty(Mono.just(1) .flatMap { cache.remove(request.link) } .then(Mono.empty())) } .flux() 

    Вы можете видеть, как использование flatMap для выполнения asynch-работы делает работу, даже если это не самая аккуратная реализация, она показала мне довольно интересный механизм, скрытый здесь.