Search code examples
springjunit4reactive

Reactive Spring Mono and doOnNext


I use spring-boot-starter-webflux, reactor-test and spring-boot-starter-test 2.0.0.M7 in my project. In my RepositoryInMemory.class has a List<String> where you can add String values by saveName(Mono<String> name) method. You can also ask all the values that are added to the list by getAllNames() method. Problem is that how to test RepositoryInMemory.class? I have RepositoryInMemoryTest.class but seems like that it does not work because List<String> returns always 0. I know that the problem is doOnNext method in RepositoryInMemory.class but I don't know why and how to solve it. Does anyone know that how I should create a valid Junit test case?

RepositoryInMemory class

package com.example

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Repository
public class RepositoryInMemory {

    private final List<String> names = new ArrayList<>();

    public Flux<String> getAllNames() {
        return Flux.fromIterable(names);
    }

    public Mono<Void> saveName(Mono<String> name) {
        return name.doOnNext(report -> names.add(report)).then();
    }
}

RepositoryInMemoryTest class

package com.example

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import reactor.core.publisher.Mono;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RepositoryInMemoryTest {

    @Autowired
    private RepositoryInMemory repository;

    @Test
    public void addDataToList_ShouldReturnOne() {
        Mono<String> name = Mono.just("Example Name");
        repository.saveName(name);
        int count = Math.toIntExact(repository.getAllNames().count().block());
        assertEquals(1, count);
    }
}

Solution

  • Just for clarification for the future readers, please use subscribe() instead of block(). Because block() will actually block the thread until the next signal is received, which is against the asynchronous concept.

    Use block() if you really want to switch back to synchronous flow.