kok202
리액터 강의 정리 ( 3강 ~ 6강 : StepVerifier, Map, flatMap, Merge)

2019. 6. 9. 01:49[공부] 영상/Reactor

StepVerifier

react-test 의 StepVerifier 으로 publisher 의 동작을 확인할 수 있다.

기대하던 이벤트와 일치하지 않는 이벤트가 발생하면 에러를 발생시킨다.

반드시 verify 라는 메소드를 호출해야한다.

verify 를 해야 subscribe 가 시작된다.

public class Part03StepVerifier {
	void expectFooBarComplete(Flux<String> flux) {
		StepVerifier.create(flux)
			.expectNext("foo")
			.expectNext("bar")
			.verifyComplete();
	}

	void expectFooBarError(Flux<String> flux) {
		StepVerifier.create(flux)
			.expectNext("foo")
			.expectNext("bar")
			.verifyError(RuntimeException.class);
	}

	void expectSkylerJesseComplete(Flux<User> flux) {
		StepVerifier.create(flux)
			.assertNext(user-> assertThat(user.getUsername()).isEqualTo("swhite"))
			.assertNext(user-> assertThat(user.getUsername()).isEqualTo("jpinkman"))
			.verifyComplete();
	}

	void expect10Elements(Flux<Long> flux) {
		StepVerifier.create(flux)
			.expectNextCount(10)
			.verifyComplete();
	}

	void expect3600Elements(Supplier<Flux<Long>> supplier) {
		StepVerifier.withVirtualTime(supplier)
			.thenAwait(Duration.ofHours(1))
			.expectNextCount(3600)
			.verifyComplete();
	}

	private void fail() {
		throw new AssertionError("workshop not implemented");
	}

}

expectNextCount : 10 개의 엘리먼트가 올 것을 기대한다.

withVirtualTime : flux 가 엘리먼트를 생성하는데 심각하게 오래 걸린다면 테스트 코드를 검증하는데 시간이 오래 걸리게 될 것이다. 이 때 withVirtualTime 메소드를 쓰면 verifier 가 core scheduler 를 가상의 스케줄러로 임의적으로 교체해서 테스트 코드의 속도를 올릴 수 있다.

thenAwait, expectNoEvent : 가상의 스케줄러의 시간을 빨리 감기하는 것

단 expectNoEvent 를 사용하려면 반드시 expectSubscription 이 선행되어야한다.

 

 

 

 

 

Map 

public class Part04Transform {
	Mono<User> capitalizeOne(Mono<User> mono) {
		return mono.map(user->{return new User(user.getUsername().toUpperCase(), user.getFirstname().toUpperCase(), user.getLastname().toUpperCase());});
	}

	Flux<User> capitalizeMany(Flux<User> flux) {
		return flux.map(user->{return new User(user.getUsername().toUpperCase(), user.getFirstname().toUpperCase(), user.getLastname().toUpperCase());});
	}

	Flux<User> asyncCapitalizeMany(Flux<User> flux) {
		return flux.flatMap(this::asyncCapitalizeUser);
	}

	Mono<User> asyncCapitalizeUser(User user) {
		return Mono.just(new User(user.getUsername().toUpperCase(), user.getFirstname().toUpperCase(), user.getLastname().toUpperCase()));
	}
}

Synchronouse 한 데이터를 변경하는 방법.

 

 

 

 

 

flatMap

Asynchronouse 한 데이터를 변경하는 방법.

flatMap 의 Return 결과는 Flux<User> 가 아니다.

flatMap 의 Return 결과는 Flux<Publisher<User>> 이다.

flatMap 자체가 변경하는 행위를 감싸는 publisher 다.

public class MyTest{
	@Test
	public void contextLoads() throws InterruptedException{
		Flux.just("a", "b", "c", "d", "e", "f", "g", "h", "i")
			.window(3)
			.flatMap(string->string.map(this::doSomething))
			.doOnNext(System.out::println)
			.blockLast();
	}
    
	private String doSomthing(String args){
		Thread.sleep(1000);
		return args.toUpperCase() + Thread.currentThread().getName();
	}
}

window : 데이터를 n 개씩 잘라서 보낸다.

flatMapSequenctial : 비동기적으로 데이터를 변형하지만 데이터를 가져올 때는 순차적으로 가져오도록해서 출력은 

 

 

 

 

 

Merge

여러개의 publisher 를 조합해서 하나의 publisher 로 만드는 것

public class Part05Merge {
	Flux<User> mergeFluxWithInterleave(Flux<User> flux1, Flux<User> flux2) {
		return flux1.mergeWith(flux2);
	}

	Flux<User> mergeFluxWithNoInterleave(Flux<User> flux1, Flux<User> flux2) {
		return flux1.concatWith(flux2);
	}

	Flux<User> createFluxFromMultipleMono(Mono<User> mono1, Mono<User> mono2) {
		return Flux.concat(mono1, mono2);
	}

}

flux1 은 delay 가 있게 오는 publisher 다

flux2 는 delay 가 없게 오는 publihser 다

concat : flux1 과 flux2 의 순서를 유지하는 것