Skip to content

Commit bfef7e6

Browse files
committed
Add JUnit tests
Signed-off-by: andreadimaio <dmaio.andrea@gmail.com>
1 parent c933460 commit bfef7e6

5 files changed

Lines changed: 247 additions & 0 deletions

File tree

modules/watsonx-ai/src/test/java/com/ibm/watsonx/ai/ContextDepedencyInjectionTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.ibm.watsonx.ai.tool.builtin.WeatherTool;
2727
import com.ibm.watsonx.ai.tool.builtin.WebCrawlerTool;
2828
import com.ibm.watsonx.ai.tool.builtin.WikipediaTool;
29+
import com.ibm.watsonx.ai.transcription.TranscriptionService;
2930
import jakarta.enterprise.context.ApplicationScoped;
3031
import jakarta.enterprise.inject.Produces;
3132
import jakarta.inject.Inject;
@@ -71,6 +72,9 @@ public class ContextDepedencyInjectionTest {
7172
@Inject
7273
TimeSeriesService timeSeriesService;
7374

75+
@Inject
76+
TranscriptionService transcriptionService;
77+
7478
@Inject
7579
ToolService toolService;
7680

@@ -142,6 +146,11 @@ void should_inject_time_series_service() {
142146
assertNotNull(timeSeriesService);
143147
}
144148

149+
@Test
150+
void should_inject_transcription_service() {
151+
assertNotNull(transcriptionService);
152+
}
153+
145154
@Test
146155
void should_inject_tool_service() {
147156
assertNotNull(toolService);
@@ -252,6 +261,16 @@ public TimeSeriesService produceTimeSeriesService() {
252261
.build();
253262
}
254263

264+
@Produces
265+
public TranscriptionService produceTranscriptionService() {
266+
return TranscriptionService.builder()
267+
.baseUrl("https://example.com")
268+
.apiKey("api-key")
269+
.projectId("project-id")
270+
.modelId("model-id")
271+
.build();
272+
}
273+
255274
@Produces
256275
public ToolService produceToolService() {
257276
return ToolService.builder()
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
* Copyright IBM Corp. 2025 - 2025
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package com.ibm.watsonx.ai;
6+
7+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
8+
import static com.github.tomakehurst.wiremock.client.WireMock.containing;
9+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
10+
import static com.github.tomakehurst.wiremock.client.WireMock.post;
11+
import static org.junit.jupiter.api.Assertions.assertEquals;
12+
import static org.junit.jupiter.api.Assertions.assertThrows;
13+
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
14+
import static org.mockito.ArgumentMatchers.any;
15+
import static org.mockito.Mockito.when;
16+
import java.io.ByteArrayInputStream;
17+
import java.io.File;
18+
import java.io.FileNotFoundException;
19+
import java.io.IOException;
20+
import java.nio.file.Files;
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.api.extension.ExtendWith;
24+
import org.mockito.junit.jupiter.MockitoExtension;
25+
import org.mockito.junit.jupiter.MockitoSettings;
26+
import org.mockito.quality.Strictness;
27+
import com.ibm.watsonx.ai.core.Language;
28+
import com.ibm.watsonx.ai.transcription.TranscriptionRequest;
29+
import com.ibm.watsonx.ai.transcription.TranscriptionService;
30+
31+
@ExtendWith(MockitoExtension.class)
32+
public class TranscriptionServiceTest extends AbstractWatsonxTest {
33+
34+
@BeforeEach
35+
void setup() {
36+
when(mockAuthenticationProvider.token()).thenReturn("token");
37+
}
38+
39+
@Test
40+
void should_transcribe_audio_successfully() throws Exception {
41+
42+
var file = Files.createTempFile("", "");
43+
file.toFile().deleteOnExit();
44+
Files.writeString(file, "the ending was terrific.");
45+
46+
wireMock.stubFor(post("/ml/v1/audio/transcriptions?version=%s".formatted(API_VERSION))
47+
.withHeader("Authorization", equalTo("Bearer token"))
48+
.withHeader("Content-Type", containing("multipart/form-data; boundary=----watsonx-ai-sdk"))
49+
.withRequestBody(containing("name=\"model\""))
50+
.withRequestBody(containing("openai/whisper-tiny"))
51+
.withRequestBody(containing("name=\"language\""))
52+
.withRequestBody(containing("it"))
53+
.withRequestBody(containing("name=\"project_id\""))
54+
.withRequestBody(containing("pid"))
55+
.withRequestBody(containing("the ending was terrific."))
56+
.willReturn(aResponse()
57+
.withStatus(200)
58+
.withHeader("Content-Type", "application/json")
59+
.withBody("""
60+
{
61+
"model": "openai/whisper-tiny",
62+
"text": "the ending was terrific.",
63+
"created_at": "2023-07-21T16:52:32.190Z",
64+
"token_count": 8
65+
}""")));
66+
67+
TranscriptionService service = TranscriptionService.builder()
68+
.authenticationProvider(mockAuthenticationProvider)
69+
.baseUrl("http://localhost:".concat(String.valueOf(wireMock.getPort())))
70+
.projectId("pid")
71+
.modelId("openai/whisper-tiny")
72+
.build();
73+
74+
var result = service.transcribe(file.toAbsolutePath().toString(), Language.ITALIAN);
75+
assertEquals("openai/whisper-tiny", result.model());
76+
assertEquals("the ending was terrific.", result.text());
77+
assertEquals(8, result.tokenCount());
78+
assertEquals("2023-07-21T16:52:32.190Z", result.createdAt());
79+
}
80+
81+
@Test
82+
void should_transcribe_audio_successfully_overriding_parameters() throws Exception {
83+
84+
var file = Files.createTempFile("", "");
85+
file.toFile().deleteOnExit();
86+
Files.writeString(file, "the ending was terrific.");
87+
88+
wireMock.stubFor(post("/ml/v1/audio/transcriptions?version=%s".formatted(API_VERSION))
89+
.withHeader("Authorization", equalTo("Bearer token"))
90+
.withHeader("Content-Type", containing("multipart/form-data; boundary=----watsonx-ai-sdk"))
91+
.withHeader(TRANSACTION_ID_HEADER, equalTo("transaction-id"))
92+
.withRequestBody(containing("name=\"model\""))
93+
.withRequestBody(containing("my-openai/whisper-tiny"))
94+
.withRequestBody(containing("name=\"language\""))
95+
.withRequestBody(containing("en"))
96+
.withRequestBody(containing("name=\"project_id\""))
97+
.withRequestBody(containing("mid"))
98+
.withRequestBody(containing("name=\"space_id\""))
99+
.withRequestBody(containing("sid"))
100+
.withRequestBody(containing("the ending was terrific."))
101+
.willReturn(aResponse()
102+
.withStatus(200)
103+
.withHeader("Content-Type", "application/json")
104+
.withBody("""
105+
{
106+
"model": "openai/whisper-tiny",
107+
"text": "the ending was terrific.",
108+
"created_at": "2023-07-21T16:52:32.190Z",
109+
"token_count": 8
110+
}""")));
111+
112+
TranscriptionService service = TranscriptionService.builder()
113+
.authenticationProvider(mockAuthenticationProvider)
114+
.baseUrl("http://localhost:".concat(String.valueOf(wireMock.getPort())))
115+
.projectId("pid")
116+
.modelId("openai/whisper-tiny")
117+
.build();
118+
119+
var result = service.transcribe(
120+
TranscriptionRequest.builder()
121+
.projectId("mid")
122+
.spaceId("sid")
123+
.modelId("my-openai/whisper-tiny")
124+
.file(file.toAbsolutePath().toString())
125+
.transactionId("transaction-id")
126+
.build());
127+
128+
assertEquals("openai/whisper-tiny", result.model());
129+
assertEquals("the ending was terrific.", result.text());
130+
assertEquals(8, result.tokenCount());
131+
assertEquals("2023-07-21T16:52:32.190Z", result.createdAt());
132+
}
133+
134+
@Test
135+
@MockitoSettings(strictness = Strictness.LENIENT)
136+
void should_throw_file_not_found_exception() {
137+
var ex = assertThrowsExactly(RuntimeException.class, () -> TranscriptionRequest.builder().file("/fileNotFound/file.txt").build());
138+
assertEquals(FileNotFoundException.class, ex.getCause().getClass());
139+
140+
TranscriptionService service = TranscriptionService.builder()
141+
.authenticationProvider(mockAuthenticationProvider)
142+
.baseUrl("http://localhost:".concat(String.valueOf(wireMock.getPort())))
143+
.projectId("pid")
144+
.modelId("openai/whisper-tiny")
145+
.build();
146+
147+
ex = assertThrowsExactly(RuntimeException.class, () -> service.transcribe(new File("/fileNotFound/file.txt"), Language.ENGLISH));
148+
assertEquals(FileNotFoundException.class, ex.getCause().getClass());
149+
}
150+
151+
@Test
152+
void should_throw_io_exception() throws Exception {
153+
154+
when(mockHttpClient.send(any(), any())).thenThrow(IOException.class);
155+
156+
withWatsonxServiceMock(() -> {
157+
158+
TranscriptionService service = TranscriptionService.builder()
159+
.authenticationProvider(mockAuthenticationProvider)
160+
.baseUrl("http://localhost:".concat(String.valueOf(wireMock.getPort())))
161+
.projectId("pid")
162+
.modelId("openai/whisper-tiny")
163+
.build();
164+
165+
var ex = assertThrows(RuntimeException.class, () -> service.transcribe(new ByteArrayInputStream("Hello".getBytes()), Language.ITALIAN));
166+
assertEquals(IOException.class, ex.getCause().getClass());
167+
});
168+
}
169+
}

modules/watsonx-ai/src/test/java/com/ibm/watsonx/ai/client/CustomRestClientTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.ibm.watsonx.ai.client.impl.CustomTimeSeriesRestClient;
2626
import com.ibm.watsonx.ai.client.impl.CustomTokenizationRestClient;
2727
import com.ibm.watsonx.ai.client.impl.CustomToolRestClient;
28+
import com.ibm.watsonx.ai.client.impl.CustomTranscriptionRestClient;
2829
import com.ibm.watsonx.ai.core.auth.Authenticator;
2930
import com.ibm.watsonx.ai.core.auth.cp4d.AuthMode;
3031
import com.ibm.watsonx.ai.core.auth.cp4d.CP4DAuthenticator;
@@ -40,6 +41,7 @@
4041
import com.ibm.watsonx.ai.timeseries.TimeSeriesService;
4142
import com.ibm.watsonx.ai.tokenization.TokenizationService;
4243
import com.ibm.watsonx.ai.tool.ToolService;
44+
import com.ibm.watsonx.ai.transcription.TranscriptionService;
4345
import com.ibm.watsonx.ai.utils.ServiceLoaderUtils;
4446

4547
public class CustomRestClientTest {
@@ -332,4 +334,22 @@ public void should_use_custom_rest_client_when_building_detection_service() thro
332334
var client = clientField.get(detectionService);
333335
assertTrue(client instanceof CustomDetectionRestClient);
334336
}
337+
338+
@Test
339+
// com.ibm.watsonx.ai.transcription.TranscriptionRestClient$TranscriptionRestClientBuilderFactory
340+
public void should_use_custom_rest_client_when_building_transcription_service() throws Exception {
341+
342+
TranscriptionService transcriptionService = TranscriptionService.builder()
343+
.apiKey("test")
344+
.baseUrl("http://localhost")
345+
.modelId("openai/whisper-tiny")
346+
.projectId("project-id")
347+
.build();
348+
349+
Class<TranscriptionService> clazz = TranscriptionService.class;
350+
var clientField = clazz.getDeclaredField("client");
351+
clientField.setAccessible(true);
352+
var client = clientField.get(transcriptionService);
353+
assertTrue(client instanceof CustomTranscriptionRestClient);
354+
}
335355
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright IBM Corp. 2025 - 2025
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package com.ibm.watsonx.ai.client.impl;
6+
7+
import com.ibm.watsonx.ai.transcription.TranscriptionRequest;
8+
import com.ibm.watsonx.ai.transcription.TranscriptionRestClient;
9+
import com.ibm.watsonx.ai.transcription.TranscriptionResult;
10+
11+
public class CustomTranscriptionRestClient extends TranscriptionRestClient {
12+
13+
CustomTranscriptionRestClient(Builder builder) {
14+
super(builder);
15+
}
16+
17+
@Override
18+
public TranscriptionResult transcribe(TranscriptionRequest request) {
19+
throw new UnsupportedOperationException("Unimplemented method 'transcribe'");
20+
}
21+
22+
public static final class CustomTranscriptionRestClientBuilderFactory implements TranscriptionRestClientBuilderFactory {
23+
@Override
24+
public Builder get() {
25+
return new CustomTranscriptionRestClient.Builder();
26+
}
27+
}
28+
29+
static final class Builder extends TranscriptionRestClient.Builder {
30+
@Override
31+
public TranscriptionRestClient build() {
32+
return new CustomTranscriptionRestClient(this);
33+
}
34+
}
35+
}

modules/watsonx-ai/src/test/java/com/ibm/watsonx/ai/utils/ServiceLoaderUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ public static void setupServiceLoader() throws Exception {
8686
"com.ibm.watsonx.ai.detection.DetectionRestClient$DetectionRestClientBuilderFactory",
8787
"com.ibm.watsonx.ai.client.impl.CustomDetectionRestClient$CustomDetectionRestClientBuilderFactory");
8888

89+
createServiceFile(metaInfServices,
90+
"com.ibm.watsonx.ai.transcription.TranscriptionRestClient$TranscriptionRestClientBuilderFactory",
91+
"com.ibm.watsonx.ai.client.impl.CustomTranscriptionRestClient$CustomTranscriptionRestClientBuilderFactory");
92+
8993
URLClassLoader tempClassLoader = new URLClassLoader(
9094
new URL[] { tempDir.toUri().toURL() },
9195
originalClassLoader

0 commit comments

Comments
 (0)