/** * Copyright 2017 Pivotal Software, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.metrics.instrument.web; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.springframework.metrics.instrument.MeterRegistry; import org.springframework.metrics.instrument.Tag; import org.springframework.metrics.annotation.Timed; import org.springframework.metrics.instrument.simple.SimpleTimer; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; class WebfluxMetricsWebFilterTest { private MeterRegistry registry; private WebTestClient client; @BeforeEach void before() { registry = mock(MeterRegistry.class); client = WebTestClient.bindToController(new Controller2()) .webFilter(new WebfluxMetricsWebFilter(registry, new DefaultWebMetricsTagProvider(), "http_server_requests")) .build(); } @Test void metricsGatheredWhenControllerIsTimed() throws Exception { SimpleTimer timer = expectTimer(); client.get().uri("/api/c2/10").exchange() .expectStatus().isOk() .expectBody().consumeAsStringWith(b -> assertThat(b).isEqualTo("10")); assertTags( Tag.of("uri", "api_c2_-id-") // FIXME doOnSuccess happens before status code is determined // Tag.of("status", "200") ); assertThat(timer.count()).isEqualTo(1); } @SuppressWarnings("unchecked") private void assertTags(Tag... match) { ArgumentCaptor<Stream> tags = ArgumentCaptor.forClass(Stream.class); verify(registry).timer(anyString(), tags.capture()); assertThat((List) tags.getValue().collect(Collectors.toList())).contains((Object[]) match); } private SimpleTimer expectTimer() { SimpleTimer timer = new SimpleTimer("http_server_requests"); //noinspection unchecked when(registry.timer(eq("http_server_requests"), any(Stream.class))).thenReturn(timer); return timer; } @RestController @Timed @RequestMapping("/api/c2") static class Controller2 { @GetMapping("/{id}") public Flux<String> successful(@PathVariable Long id) { return Flux.just(id.toString()); } } }