Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e121dd7

Browse files
committed
Add Redis integration tests
Signed-off-by: Hyunwoo Jung <hyunwoojung@kakao.com>
1 parent 639d64f commit e121dd7

File tree

5 files changed

+298
-0
lines changed

5 files changed

+298
-0
lines changed

‎pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@
134134
<nashorn.version>15.6</nashorn.version>
135135
<beanshell.version>2.0b6</beanshell.version>
136136
<jruby.version>9.4.12.0</jruby.version>
137+
<lettuce.version>6.6.0.RELEASE</lettuce.version>
138+
<testcontainers-redis.version>2.2.4</testcontainers-redis.version>
137139

138140
<!-- samples dependencies -->
139141
<spring-rabbit.version>${spring-amqp.version}</spring-rabbit.version>

‎spring-batch-infrastructure/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,18 @@
559559
<version>${jruby.version}</version>
560560
<scope>test</scope>
561561
</dependency>
562+
<dependency>
563+
<groupId>io.lettuce</groupId>
564+
<artifactId>lettuce-core</artifactId>
565+
<version>${lettuce.version}</version>
566+
<scope>test</scope>
567+
</dependency>
568+
<dependency>
569+
<groupId>com.redis</groupId>
570+
<artifactId>testcontainers-redis</artifactId>
571+
<version>${testcontainers-redis.version}</version>
572+
<scope>test</scope>
573+
</dependency>
562574

563575
<!-- provided dependencies -->
564576
<dependency>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 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.batch.item.redis;
18+
19+
import com.redis.testcontainers.RedisContainer;
20+
import org.junit.jupiter.api.BeforeEach;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.extension.ExtendWith;
23+
import org.springframework.batch.item.ExecutionContext;
24+
import org.springframework.batch.item.redis.example.Person;
25+
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
26+
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
27+
import org.springframework.data.redis.core.RedisTemplate;
28+
import org.springframework.data.redis.core.ScanOptions;
29+
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
30+
import org.springframework.data.redis.serializer.StringRedisSerializer;
31+
import org.springframework.test.context.junit.jupiter.SpringExtension;
32+
import org.testcontainers.junit.jupiter.Container;
33+
import org.testcontainers.junit.jupiter.Testcontainers;
34+
import org.testcontainers.utility.DockerImageName;
35+
36+
import java.util.ArrayList;
37+
import java.util.List;
38+
39+
import static org.hamcrest.MatcherAssert.assertThat;
40+
import static org.hamcrest.Matchers.containsInAnyOrder;
41+
42+
/**
43+
* @author Hyunwoo Jung
44+
*/
45+
@Testcontainers(disabledWithoutDocker = true)
46+
@ExtendWith(SpringExtension.class)
47+
class RedisItemReaderIntegrationTests {
48+
49+
private static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis:8.0.2");
50+
51+
@Container
52+
public static RedisContainer redis = new RedisContainer(REDIS_IMAGE);
53+
54+
private RedisItemReader<String, Person> reader;
55+
56+
private RedisTemplate<String, Person> template;
57+
58+
@BeforeEach
59+
void setUp() {
60+
this.template = setUpRedisTemplate();
61+
this.template.getConnectionFactory().getConnection().serverCommands().flushAll();
62+
}
63+
64+
@Test
65+
void testRead() throws Exception {
66+
this.template.opsForValue().set("person:1", new Person(1, "foo"));
67+
this.template.opsForValue().set("person:2", new Person(2, "bar"));
68+
this.template.opsForValue().set("person:3", new Person(3, "baz"));
69+
this.template.opsForValue().set("person:4", new Person(4, "qux"));
70+
this.template.opsForValue().set("person:5", new Person(5, "quux"));
71+
72+
RedisTemplate<String, Person> redisTemplate = setUpRedisTemplate();
73+
ScanOptions scanOptions = ScanOptions.scanOptions().match("person:*").count(10).build();
74+
this.reader = new RedisItemReader<>(redisTemplate, scanOptions);
75+
76+
this.reader.open(new ExecutionContext());
77+
78+
List<Person> items = new ArrayList<>();
79+
for (int i = 0; i < 5; i++) {
80+
items.add(this.reader.read());
81+
}
82+
83+
assertThat(items, containsInAnyOrder(new Person(1, "foo"), new Person(2, "bar"), new Person(3, "baz"),
84+
new Person(4, "qux"), new Person(5, "quux")));
85+
}
86+
87+
private RedisTemplate<String, Person> setUpRedisTemplate() {
88+
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(
89+
new RedisStandaloneConfiguration(redis.getRedisHost(), redis.getRedisPort()));
90+
connectionFactory.afterPropertiesSet();
91+
92+
RedisTemplate<String, Person> redisTemplate = new RedisTemplate<>();
93+
redisTemplate.setConnectionFactory(connectionFactory);
94+
redisTemplate.setKeySerializer(new StringRedisSerializer());
95+
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
96+
redisTemplate.afterPropertiesSet();
97+
98+
return redisTemplate;
99+
}
100+
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright 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.batch.item.redis;
18+
19+
import com.redis.testcontainers.RedisContainer;
20+
import org.junit.jupiter.api.BeforeEach;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.extension.ExtendWith;
23+
import org.springframework.batch.item.Chunk;
24+
import org.springframework.batch.item.redis.example.Person;
25+
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
26+
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
27+
import org.springframework.data.redis.core.RedisTemplate;
28+
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
29+
import org.springframework.data.redis.serializer.StringRedisSerializer;
30+
import org.springframework.test.context.junit.jupiter.SpringExtension;
31+
import org.testcontainers.junit.jupiter.Container;
32+
import org.testcontainers.junit.jupiter.Testcontainers;
33+
import org.testcontainers.utility.DockerImageName;
34+
35+
import static org.junit.jupiter.api.Assertions.*;
36+
37+
/**
38+
* @author Hyunwoo Jung
39+
*/
40+
@Testcontainers(disabledWithoutDocker = true)
41+
@ExtendWith(SpringExtension.class)
42+
class RedisItemWriterIntegrationTests {
43+
44+
private static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis:8.0.2");
45+
46+
@Container
47+
public static RedisContainer redis = new RedisContainer(REDIS_IMAGE);
48+
49+
private RedisItemWriter<String, Person> writer;
50+
51+
private RedisTemplate<String, Person> template;
52+
53+
@BeforeEach
54+
void setUp() {
55+
this.template = setUpRedisTemplate();
56+
this.template.getConnectionFactory().getConnection().serverCommands().flushAll();
57+
}
58+
59+
@Test
60+
void testWrite() throws Exception {
61+
RedisTemplate<String, Person> redisTemplate = setUpRedisTemplate();
62+
this.writer = new RedisItemWriter<>();
63+
this.writer.setRedisTemplate(redisTemplate);
64+
this.writer.setItemKeyMapper(p -> "person:" + p.getId());
65+
this.writer.setDelete(false);
66+
67+
Chunk<Person> items = new Chunk<>(new Person(1, "foo"), new Person(2, "bar"), new Person(3, "baz"),
68+
new Person(4, "qux"), new Person(5, "quux"));
69+
this.writer.write(items);
70+
71+
assertEquals(new Person(1, "foo"), this.template.opsForValue().get("person:1"));
72+
assertEquals(new Person(2, "bar"), this.template.opsForValue().get("person:2"));
73+
assertEquals(new Person(3, "baz"), this.template.opsForValue().get("person:3"));
74+
assertEquals(new Person(4, "qux"), this.template.opsForValue().get("person:4"));
75+
assertEquals(new Person(5, "quux"), this.template.opsForValue().get("person:5"));
76+
}
77+
78+
@Test
79+
void testDelete() throws Exception {
80+
this.template.opsForValue().set("person:1", new Person(1, "foo"));
81+
this.template.opsForValue().set("person:2", new Person(2, "bar"));
82+
this.template.opsForValue().set("person:3", new Person(3, "baz"));
83+
this.template.opsForValue().set("person:4", new Person(4, "qux"));
84+
this.template.opsForValue().set("person:5", new Person(5, "quux"));
85+
86+
RedisTemplate<String, Person> redisTemplate = setUpRedisTemplate();
87+
this.writer = new RedisItemWriter<>();
88+
this.writer.setRedisTemplate(redisTemplate);
89+
this.writer.setItemKeyMapper(p -> "person:" + p.getId());
90+
this.writer.setDelete(true);
91+
92+
Chunk<Person> items = new Chunk<>(new Person(1, "foo"), new Person(2, "bar"), new Person(3, "baz"),
93+
new Person(4, "qux"), new Person(5, "quux"));
94+
this.writer.write(items);
95+
96+
assertFalse(this.template.hasKey("person:1"));
97+
assertFalse(this.template.hasKey("person:2"));
98+
assertFalse(this.template.hasKey("person:3"));
99+
assertFalse(this.template.hasKey("person:4"));
100+
assertFalse(this.template.hasKey("person:5"));
101+
}
102+
103+
private RedisTemplate<String, Person> setUpRedisTemplate() {
104+
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(
105+
new RedisStandaloneConfiguration(redis.getRedisHost(), redis.getRedisPort()));
106+
connectionFactory.afterPropertiesSet();
107+
108+
RedisTemplate<String, Person> redisTemplate = new RedisTemplate<>();
109+
redisTemplate.setConnectionFactory(connectionFactory);
110+
redisTemplate.setKeySerializer(new StringRedisSerializer());
111+
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
112+
redisTemplate.afterPropertiesSet();
113+
114+
return redisTemplate;
115+
}
116+
117+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 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.batch.item.redis.example;
18+
19+
import java.io.Serial;
20+
import java.io.Serializable;
21+
import java.util.Objects;
22+
23+
/**
24+
* @author Hyunwoo Jung
25+
*/
26+
public class Person implements Serializable {
27+
28+
@Serial
29+
private static final long serialVersionUID = 2396556853218591048L;
30+
31+
private long id;
32+
33+
private String name;
34+
35+
public Person(long id, String name) {
36+
this.id = id;
37+
this.name = name;
38+
}
39+
40+
public long getId() {
41+
return id;
42+
}
43+
44+
public String getName() {
45+
return name;
46+
}
47+
48+
@Override
49+
public boolean equals(Object o) {
50+
if (o == null || getClass() != o.getClass())
51+
return false;
52+
Person person = (Person) o;
53+
return id == person.id && Objects.equals(name, person.name);
54+
}
55+
56+
@Override
57+
public int hashCode() {
58+
return Objects.hash(id, name);
59+
}
60+
61+
@Override
62+
public String toString() {
63+
return "Person{id=" + id + ", name=" + name + "}";
64+
}
65+
66+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /