Skip to content

Commit e569683

Browse files
author
ALIOTTI Simon
committed
feat: add IT test
1 parent 906e5e5 commit e569683

1 file changed

Lines changed: 132 additions & 0 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.demo.tuto.crypto.it.service;
2+
3+
import com.demo.tuto.crypto.e2e.sharedConf.SharedWiremock;
4+
import com.demo.tuto.crypto.exception.CryptoException;
5+
import com.demo.tuto.crypto.helper.CommonServiceHelper;
6+
import com.demo.tuto.crypto.mapper.CoinPriceBuilder;
7+
import com.demo.tuto.crypto.mapper.CoinPriceMapper;
8+
import com.demo.tuto.crypto.mapper.CoinPriceMapperImpl;
9+
import com.demo.tuto.crypto.pojo.SimpleCoinPrice;
10+
import com.demo.tuto.crypto.service.CoinService;
11+
import com.demo.tuto.crypto.service.client.CoinGeckoClientService;
12+
import com.github.tomakehurst.wiremock.WireMockServer;
13+
import org.junit.jupiter.api.BeforeAll;
14+
import org.junit.jupiter.api.Test;
15+
import org.junit.jupiter.api.extension.ExtendWith;
16+
import org.springframework.beans.factory.annotation.Autowired;
17+
import org.springframework.boot.test.context.TestConfiguration;
18+
import org.springframework.context.annotation.Bean;
19+
import org.springframework.http.HttpStatus;
20+
import org.springframework.test.context.ContextConfiguration;
21+
import org.springframework.test.context.junit.jupiter.SpringExtension;
22+
import org.springframework.web.reactive.function.client.WebClient;
23+
24+
import java.math.BigDecimal;
25+
import java.util.List;
26+
27+
import static com.github.tomakehurst.wiremock.client.WireMock.*;
28+
import static org.junit.jupiter.api.Assertions.*;
29+
30+
/**
31+
* Lightweight integration test for CoinPriceService
32+
* <p>
33+
* Context:
34+
* - Loads only the beans needed for this test (WebClient, CoinGeckoClientService, CoinPriceService)
35+
* - No SpringBootTest → keeps the context lightweight and fast
36+
*
37+
* @ContextConfiguration(classes = CoinServiceIT.TestConfig.class)
38+
* → Loads only the TestConfig class into the Spring context
39+
* → Allows @Autowired injection for beans declared in TestConfig
40+
* @TestConfiguration → Indicates that TestConfig is a configuration specifically for tests
41+
* → Beans defined here do not affect the real application context
42+
* @ExtendWith(SpringExtension.class) → Enables Spring support in JUnit 5
43+
* → Allows bean injection and the use of Spring test annotations
44+
*/
45+
@ExtendWith(SpringExtension.class)
46+
@ContextConfiguration(classes = CoinServiceIT.TestConfig.class) // Load a lightweight specified context
47+
public class CoinServiceIT {
48+
49+
private final static WireMockServer wireMock = SharedWiremock.getInstance();
50+
51+
@Autowired
52+
private CoinService coinService;
53+
54+
@BeforeAll
55+
public static void resetWiremockServer() {
56+
wireMock.resetAll();
57+
}
58+
59+
@Test
60+
void givenBitcoin_whenFetchCoinPrices_thenReturnBitcoinPrice() throws CryptoException {
61+
62+
// Given
63+
final SimpleCoinPrice expectedResult = new SimpleCoinPrice("bitcoin", "usd", BigDecimal.valueOf(89480), null);
64+
65+
wireMock.stubFor(get(urlPathEqualTo("/simple/price"))
66+
.withQueryParam("ids", equalTo("bitcoin"))
67+
.withQueryParam("vs_currencies", equalTo("usd"))
68+
.willReturn(aResponse()
69+
.withHeader("Content-Type", "application/json")
70+
.withBody("{ \"bitcoin\": { \"usd\": 89480 } }")
71+
.withStatus(200)));
72+
// Act
73+
final List<SimpleCoinPrice> bitcoin = coinService.fetchCoinPrices(List.of("bitcoin"));
74+
75+
// Assert
76+
assertNotNull(bitcoin);
77+
assertEquals(1, bitcoin.size());
78+
assertEquals(expectedResult.coinId(), bitcoin.getFirst().coinId());
79+
assertEquals(expectedResult.price(), bitcoin.getFirst().price());
80+
assertEquals(expectedResult.vsCurrency(), bitcoin.getFirst().vsCurrency());
81+
}
82+
83+
@Test
84+
void givenBitcoin_whenFetchCoinPriceAndExternalApiReturn409_thenReturnThrowCryptoException() throws CryptoException {
85+
86+
// Given
87+
wireMock.stubFor(get(urlPathEqualTo("/simple/price"))
88+
.withQueryParam("ids", equalTo("bitcoin"))
89+
.withQueryParam("vs_currencies", equalTo("usd"))
90+
.willReturn(aResponse()
91+
.withHeader("Content-Type", "application/json")
92+
.withBody("")
93+
.withStatus(409)));
94+
// Act
95+
final CryptoException cryptoException = assertThrows(CryptoException.class, () -> coinService.fetchCoinPrices(List.of("bitcoin")));
96+
97+
// Assert
98+
assertEquals(CommonServiceHelper.generateServiceErrorMessageFromWebclientException(
99+
"Coin Gecko", "Query prices by coin ids", HttpStatus.CONFLICT.getReasonPhrase(), ""), cryptoException.getMessage());
100+
}
101+
102+
@TestConfiguration
103+
static class TestConfig {
104+
105+
@Bean
106+
CoinPriceBuilder coinPriceBuilder() {
107+
return new CoinPriceBuilder();
108+
}
109+
110+
@Bean
111+
CoinPriceMapper coinPriceMapper() {
112+
return new CoinPriceMapperImpl();
113+
}
114+
115+
@Bean
116+
WebClient webClient() {
117+
return WebClient.builder().baseUrl(wireMock.baseUrl()).build();
118+
}
119+
120+
@Bean
121+
CoinGeckoClientService clientService(WebClient webClient) {
122+
return new CoinGeckoClientService(webClient);
123+
}
124+
125+
@Bean
126+
CoinService coinService(CoinGeckoClientService clientService, CoinPriceBuilder coinPriceBuilder,
127+
CoinPriceMapper coinPriceMapper) {
128+
return new CoinService(clientService, coinPriceBuilder, coinPriceMapper);
129+
}
130+
}
131+
132+
}

0 commit comments

Comments
 (0)