Skip to content

Commit 97c6ebd

Browse files
test(retrofit2): add test to verify retrofit2 error handling
1 parent b12d270 commit 97c6ebd

File tree

3 files changed

+135
-1
lines changed

3 files changed

+135
-1
lines changed

clouddriver-core/clouddriver-core.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ dependencies {
6363
testImplementation "com.google.cloud:google-cloud-secretmanager"
6464
testImplementation "io.spinnaker.kork:kork-cloud-config-server"
6565
testImplementation "com.squareup.retrofit2:retrofit-mock"
66+
testImplementation "com.github.tomakehurst:wiremock-jre8-standalone"
6667
}

clouddriver-core/src/main/java/com/netflix/spinnaker/clouddriver/config/RetrofitConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
@Configuration
3232
@EnableConfigurationProperties(Front50ConfigurationProperties.class)
33-
class RetrofitConfig {
33+
public class RetrofitConfig {
3434

3535
@Bean
3636
@ConditionalOnProperty(name = "services.front50.enabled", matchIfMissing = true)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright 2025 OpsMx, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
package com.netflix.spinnaker.clouddriver.safety;
18+
19+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
20+
import static com.github.tomakehurst.wiremock.client.WireMock.anyRequestedFor;
21+
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
22+
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
23+
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
24+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
25+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
26+
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
27+
28+
import com.fasterxml.jackson.core.JsonProcessingException;
29+
import com.fasterxml.jackson.databind.ObjectMapper;
30+
import com.github.tomakehurst.wiremock.client.WireMock;
31+
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
32+
import com.netflix.spectator.api.NoopRegistry;
33+
import com.netflix.spinnaker.clouddriver.config.RetrofitConfig;
34+
import com.netflix.spinnaker.clouddriver.core.services.Front50Service;
35+
import com.netflix.spinnaker.clouddriver.model.NoopClusterProvider;
36+
import com.netflix.spinnaker.config.DefaultServiceClientProvider;
37+
import com.netflix.spinnaker.config.okhttp3.DefaultOkHttpClientBuilderProvider;
38+
import com.netflix.spinnaker.config.okhttp3.OkHttpClientProvider;
39+
import com.netflix.spinnaker.kork.dynamicconfig.DynamicConfigService;
40+
import com.netflix.spinnaker.kork.retrofit.Retrofit2ServiceFactory;
41+
import com.netflix.spinnaker.kork.retrofit.exceptions.SpinnakerHttpException;
42+
import com.netflix.spinnaker.moniker.Moniker;
43+
import com.netflix.spinnaker.okhttp.OkHttpClientConfigurationProperties;
44+
import com.netflix.spinnaker.okhttp.SpinnakerRequestHeaderInterceptor;
45+
import java.util.List;
46+
import java.util.Map;
47+
import java.util.Optional;
48+
import okhttp3.OkHttpClient;
49+
import org.junit.jupiter.api.BeforeEach;
50+
import org.junit.jupiter.api.Test;
51+
import org.junit.jupiter.api.extension.RegisterExtension;
52+
import org.springframework.beans.factory.annotation.Autowired;
53+
import org.springframework.boot.test.context.SpringBootTest;
54+
import org.springframework.context.annotation.Bean;
55+
import org.springframework.context.annotation.Configuration;
56+
import org.springframework.http.HttpStatus;
57+
import org.springframework.test.context.DynamicPropertyRegistry;
58+
import org.springframework.test.context.DynamicPropertySource;
59+
60+
@SpringBootTest(
61+
classes = {
62+
RetrofitConfig.class,
63+
OkHttpClientProvider.class,
64+
TrafficGuardTest.TestConfig.class,
65+
DefaultServiceClientProvider.class,
66+
Retrofit2ServiceFactory.class,
67+
DefaultOkHttpClientBuilderProvider.class,
68+
OkHttpClient.class,
69+
OkHttpClientConfigurationProperties.class,
70+
ObjectMapper.class
71+
})
72+
public class TrafficGuardTest {
73+
private final String APP_NAME = "testApp";
74+
75+
@RegisterExtension
76+
static WireMockExtension wmFront50 =
77+
WireMockExtension.newInstance().options(wireMockConfig().dynamicPort()).build();
78+
79+
@Autowired ObjectMapper objectMapper;
80+
81+
@Autowired Front50Service front50Service;
82+
83+
@Autowired SpinnakerRequestHeaderInterceptor requestHeaderInterceptor;
84+
85+
TrafficGuard trafficGuard;
86+
87+
@DynamicPropertySource
88+
static void registerUrls(DynamicPropertyRegistry registry) {
89+
// Configure wiremock's random ports into clouddriver
90+
System.out.println("wiremock front50 url: " + wmFront50.baseUrl());
91+
registry.add("services.front50.base-url", wmFront50::baseUrl);
92+
}
93+
94+
@BeforeEach
95+
void init() throws JsonProcessingException {
96+
wmFront50.stubFor(
97+
WireMock.get(urlMatching("/v2/applications/" + APP_NAME))
98+
.willReturn(
99+
aResponse()
100+
.withStatus(HttpStatus.INTERNAL_SERVER_ERROR.value())
101+
.withBody(
102+
objectMapper.writeValueAsString(
103+
Map.of("error", "Internal Server Error")))));
104+
105+
trafficGuard =
106+
new TrafficGuard(
107+
List.of(new NoopClusterProvider()),
108+
Optional.of(front50Service),
109+
new NoopRegistry(),
110+
new DynamicConfigService.NoopDynamicConfig());
111+
}
112+
113+
@Test
114+
void verifyErrorHandlingExecutorCallAdapterFactory_with_500_exception() {
115+
Moniker moniker = Moniker.builder().app(APP_NAME).build();
116+
117+
assertThatThrownBy(() -> trafficGuard.hasDisableLock(moniker, "acc1", "location1"))
118+
.isInstanceOf(SpinnakerHttpException.class);
119+
120+
wmFront50.verify(getRequestedFor(urlPathEqualTo("/v2/applications/" + APP_NAME)));
121+
122+
wmFront50.verify(1, anyRequestedFor(anyUrl()));
123+
}
124+
125+
@Configuration
126+
static class TestConfig {
127+
128+
@Bean
129+
SpinnakerRequestHeaderInterceptor spinnakerRequestHeaderInterceptor() {
130+
return new SpinnakerRequestHeaderInterceptor(false);
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)