Skip to content

Commit dfb3e5c

Browse files
committed
add more tests
Signed-off-by: Alexandros Pappas <[email protected]>
1 parent e1969be commit dfb3e5c

File tree

4 files changed

+179
-5
lines changed

4 files changed

+179
-5
lines changed

.github/workflows/pr-check.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,18 @@ jobs:
2525
run: |
2626
./mvnw clean install -pl spring-ai-model -DskipTests
2727
28-
- name: Run OpenAI Image API integration tests
28+
- name: Run OpenAI Image Model integration tests
2929
env:
3030
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
3131
run: |
32-
./mvnw -pl models/spring-ai-openai -Pintegration-tests -Dit.test=OpenAiImageApiIT,OpenAiImageApiStreamingIT verify
32+
./mvnw -pl models/spring-ai-openai -Pintegration-tests -Dit.test=OpenAiImageModelIT,OpenAiImageModelNoOpApiKeysIT,OpenAiImageModelObservationIT,OpenAiImageModelStreamingIT,OpenAiImageModelWithImageResponseMetadataTests,OpenAiImageApiBuilderTests,OpenAiImageApiIT,OpenAiImageApiStreamingIT verify
3333
34-
- name: Run OpenAI Image Model integration tests
34+
- name: Run OpenAI Image AutoConfiguration tests
3535
env:
3636
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
3737
run: |
38-
./mvnw -pl models/spring-ai-openai -Pintegration-tests -Dit.test=OpenAiImageModelObservationIT,OpenAiImageModelStreamingIT verify
38+
./mvnw -pl auto-configurations/models/spring-ai-autoconfigure-model-openai -Pintegration-tests -Dit.test=OpenAiImageAutoConfigurationIT verify
39+
40+
- name: Run OpenAI Image Properties tests
41+
run: |
42+
./mvnw test -pl auto-configurations/models/spring-ai-autoconfigure-model-openai -Dtest=OpenAiPropertiesTests#imageOptionsTest,OpenAiPropertiesTests#imageGptImageOptionsTest
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2023-2025 the original author or authors.
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+
* https://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 org.springframework.ai.model.openai.autoconfigure;
18+
19+
import org.apache.commons.logging.Log;
20+
import org.apache.commons.logging.LogFactory;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
23+
import reactor.core.publisher.Flux;
24+
25+
import org.springframework.ai.image.ImagePrompt;
26+
import org.springframework.ai.image.ImageResponse;
27+
import org.springframework.ai.openai.OpenAiImageModel;
28+
import org.springframework.ai.openai.OpenAiImageOptions;
29+
import org.springframework.ai.openai.api.OpenAiImageApi;
30+
import org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration;
31+
import org.springframework.boot.autoconfigure.AutoConfigurations;
32+
import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration;
33+
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
34+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
35+
36+
import static org.assertj.core.api.Assertions.assertThat;
37+
38+
/**
39+
* Integration tests for {@link OpenAiImageAutoConfiguration}.
40+
*
41+
* @author Alexandros Pappas
42+
* @since 1.1.0
43+
*/
44+
@EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".*")
45+
public class OpenAiImageAutoConfigurationIT {
46+
47+
private static final Log logger = LogFactory.getLog(OpenAiImageAutoConfigurationIT.class);
48+
49+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
50+
.withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"),
51+
"spring.ai.openai.image.options.model=gpt-image-1-mini")
52+
.withConfiguration(
53+
AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class,
54+
WebClientAutoConfiguration.class, OpenAiImageAutoConfiguration.class));
55+
56+
@Test
57+
void imageModelAutoConfigured() {
58+
this.contextRunner.run(context -> {
59+
assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty();
60+
assertThat(context.getBeansOfType(OpenAiImageApi.class)).isNotEmpty();
61+
});
62+
}
63+
64+
@Test
65+
void generateImage() {
66+
this.contextRunner.run(context -> {
67+
OpenAiImageModel imageModel = context.getBean(OpenAiImageModel.class);
68+
69+
assertThat(imageModel).isNotNull();
70+
71+
ImagePrompt prompt = new ImagePrompt("A simple red circle");
72+
ImageResponse response = imageModel.call(prompt);
73+
74+
assertThat(response).isNotNull();
75+
assertThat(response.getResults()).isNotEmpty();
76+
assertThat(response.getResult().getOutput().getB64Json()).isNotEmpty();
77+
78+
logger
79+
.info("Generated image with base64 length: " + response.getResult().getOutput().getB64Json().length());
80+
});
81+
}
82+
83+
@Test
84+
void streamImage() {
85+
this.contextRunner.run(context -> {
86+
OpenAiImageModel imageModel = context.getBean(OpenAiImageModel.class);
87+
88+
assertThat(imageModel).isNotNull();
89+
90+
OpenAiImageOptions options = OpenAiImageOptions.builder()
91+
.model(OpenAiImageApi.ImageModel.GPT_IMAGE_1_MINI.getValue())
92+
.stream(true)
93+
.partialImages(1)
94+
.build();
95+
96+
ImagePrompt prompt = new ImagePrompt("A blue square", options);
97+
Flux<ImageResponse> imageStream = imageModel.stream(prompt);
98+
99+
ImageResponse response = imageStream.blockFirst();
100+
101+
assertThat(response).isNotNull();
102+
assertThat(response.getResults()).hasSize(1);
103+
assertThat(response.getResult().getOutput().getB64Json()).isNotEmpty();
104+
logger.info("Received streaming image chunk");
105+
});
106+
}
107+
108+
@Test
109+
void imageModelDisabled() {
110+
new ApplicationContextRunner()
111+
.withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"),
112+
"spring.ai.model.image=none")
113+
.withConfiguration(
114+
AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class,
115+
WebClientAutoConfiguration.class, OpenAiImageAutoConfiguration.class))
116+
.run(context -> assertThat(context.getBeansOfType(OpenAiImageModel.class)).isEmpty());
117+
}
118+
119+
@Test
120+
void imageModelExplicitlyEnabled() {
121+
new ApplicationContextRunner()
122+
.withPropertyValues("spring.ai.openai.apiKey=" + System.getenv("OPENAI_API_KEY"),
123+
"spring.ai.model.image=openai")
124+
.withConfiguration(
125+
AutoConfigurations.of(SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class,
126+
WebClientAutoConfiguration.class, OpenAiImageAutoConfiguration.class))
127+
.run(context -> assertThat(context.getBeansOfType(OpenAiImageModel.class)).isNotEmpty());
128+
}
129+
130+
}

auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,46 @@ public void imageOptionsTest() {
539539
});
540540
}
541541

542+
@Test
543+
public void imageGptImageOptionsTest() {
544+
this.contextRunner.withPropertyValues(
545+
// @formatter:off
546+
"spring.ai.openai.api-key=API_KEY",
547+
"spring.ai.openai.base-url=TEST_BASE_URL",
548+
549+
"spring.ai.openai.image.options.model=gpt-image-1",
550+
"spring.ai.openai.image.options.quality=high",
551+
"spring.ai.openai.image.options.size=1024x1024",
552+
"spring.ai.openai.image.options.background=transparent",
553+
"spring.ai.openai.image.options.moderation=low",
554+
"spring.ai.openai.image.options.output_compression=85",
555+
"spring.ai.openai.image.options.output_format=png",
556+
"spring.ai.openai.image.options.partial_images=2",
557+
"spring.ai.openai.image.options.stream=true",
558+
"spring.ai.openai.image.options.user=userXYZ"
559+
)
560+
// @formatter:on
561+
.withConfiguration(AutoConfigurations.of(OpenAiImageAutoConfiguration.class))
562+
.run(context -> {
563+
var imageProperties = context.getBean(OpenAiImageProperties.class);
564+
var connectionProperties = context.getBean(OpenAiConnectionProperties.class);
565+
566+
assertThat(connectionProperties.getBaseUrl()).isEqualTo("TEST_BASE_URL");
567+
assertThat(connectionProperties.getApiKey()).isEqualTo("API_KEY");
568+
569+
assertThat(imageProperties.getOptions().getModel()).isEqualTo("gpt-image-1");
570+
assertThat(imageProperties.getOptions().getQuality()).isEqualTo("high");
571+
assertThat(imageProperties.getOptions().getSize()).isEqualTo("1024x1024");
572+
assertThat(imageProperties.getOptions().getBackground()).isEqualTo("transparent");
573+
assertThat(imageProperties.getOptions().getModeration()).isEqualTo("low");
574+
assertThat(imageProperties.getOptions().getOutputCompression()).isEqualTo(85);
575+
assertThat(imageProperties.getOptions().getOutputFormat()).isEqualTo("png");
576+
assertThat(imageProperties.getOptions().getPartialImages()).isEqualTo(2);
577+
assertThat(imageProperties.getOptions().getStream()).isTrue();
578+
assertThat(imageProperties.getOptions().getUser()).isEqualTo("userXYZ");
579+
});
580+
}
581+
542582
@Test
543583
void embeddingActivation() {
544584

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/image/api/OpenAiImageApiBuilderTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void dynamicApiKeyRestClient() throws InterruptedException {
158158
this.mockWebServer.enqueue(mockResponse);
159159

160160
OpenAiImageApi.OpenAiImageRequest request = new OpenAiImageApi.OpenAiImageRequest("Test",
161-
OpenAiImageApi.ImageModel.GPT_IMAGE_1_MINI.getValue());
161+
OpenAiImageApi.ImageModel.DALL_E_3.getValue());
162162
ResponseEntity<OpenAiImageApi.OpenAiImageResponse> response = api.createImage(request);
163163
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
164164
RecordedRequest recordedRequest = this.mockWebServer.takeRequest();

0 commit comments

Comments
 (0)