Skip to content

Commit dcfb683

Browse files
committed
Update test to verify transaction visibility for all rangeWithScores methods
Signed-off-by: LeeHyungGeol <rjf1138@naver.com>
1 parent 8b5b266 commit dcfb683

File tree

1 file changed

+75
-12
lines changed

1 file changed

+75
-12
lines changed

src/test/java/org/springframework/data/redis/core/TransactionalStringRedisTemplateTests.java

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.sql.SQLException;
2323
import java.util.LinkedHashMap;
2424
import java.util.Map;
25+
import java.util.Set;
2526
import java.util.stream.Stream;
2627

2728
import javax.sql.DataSource;
@@ -42,6 +43,7 @@
4243
import org.springframework.data.redis.connection.RedisConnectionFactory;
4344
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
4445
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
46+
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
4547
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
4648
import org.springframework.transaction.support.TransactionTemplate;
4749

@@ -117,8 +119,9 @@ void visibilityDuringManagedTransaction() throws SQLException {
117119
.containsEntry("isMember(inside)", false);
118120
}
119121

122+
@SuppressWarnings("unchecked")
120123
@Test // GH-3187
121-
void allRangeWithScoresMethodsInTransactionShouldNotReturnNull() throws SQLException {
124+
void allRangeWithScoresMethodsShouldExecuteImmediatelyInTransaction() throws SQLException {
122125

123126
DataSource ds = mock(DataSource.class);
124127
when(ds.getConnection()).thenReturn(mock(Connection.class));
@@ -127,23 +130,83 @@ void allRangeWithScoresMethodsInTransactionShouldNotReturnNull() throws SQLExcep
127130
TransactionTemplate txTemplate = new TransactionTemplate(txMgr);
128131
txTemplate.afterPropertiesSet();
129132

130-
stringTemplate.opsForZSet().add("testzset", "member1", 1.0);
131-
stringTemplate.opsForZSet().add("testzset", "member2", 2.0);
133+
// Add data outside transaction
134+
stringTemplate.opsForZSet().add("testzset", "outside1", 1.0);
135+
stringTemplate.opsForZSet().add("testzset", "outside2", 2.0);
132136

133137
Map<String, Object> result = txTemplate.execute(x -> {
134138
Map<String, Object> ops = new LinkedHashMap<>();
135-
ops.put("rangeWithScores", stringTemplate.opsForZSet().rangeWithScores("testzset", 0, -1));
136-
ops.put("reverseRangeWithScores", stringTemplate.opsForZSet().reverseRangeWithScores("testzset", 0, -1));
137-
ops.put("rangeByScoreWithScores", stringTemplate.opsForZSet().rangeByScoreWithScores("testzset", 1.0, 2.0));
138-
ops.put("reverseRangeByScoreWithScores", stringTemplate.opsForZSet().reverseRangeByScoreWithScores("testzset", 1.0, 2.0));
139+
140+
// Query data added outside transaction (should execute immediately)
141+
ops.put("rangeWithScores_before",
142+
stringTemplate.opsForZSet().rangeWithScores("testzset", 0, -1));
143+
ops.put("reverseRangeWithScores_before",
144+
stringTemplate.opsForZSet().reverseRangeWithScores("testzset", 0, -1));
145+
ops.put("rangeByScoreWithScores_before",
146+
stringTemplate.opsForZSet().rangeByScoreWithScores("testzset", 1.0, 2.0));
147+
ops.put("reverseRangeByScoreWithScores_before",
148+
stringTemplate.opsForZSet().reverseRangeByScoreWithScores("testzset", 1.0, 2.0));
149+
150+
// Add inside transaction (goes into multi/exec queue)
151+
ops.put("add_result", stringTemplate.opsForZSet().add("testzset", "inside", 3.0));
152+
153+
// Changes made inside transaction should not be visible yet (read executes immediately)
154+
ops.put("rangeWithScores_after",
155+
stringTemplate.opsForZSet().rangeWithScores("testzset", 0, -1));
156+
ops.put("reverseRangeWithScores_after",
157+
stringTemplate.opsForZSet().reverseRangeWithScores("testzset", 0, -1));
158+
ops.put("rangeByScoreWithScores_after",
159+
stringTemplate.opsForZSet().rangeByScoreWithScores("testzset", 1.0, 3.0));
160+
ops.put("reverseRangeByScoreWithScores_after",
161+
stringTemplate.opsForZSet().reverseRangeByScoreWithScores("testzset", 1.0, 3.0));
162+
139163
return ops;
140164
});
141165

142-
// Issue #3187: All should return data, not null
143-
assertThat(result.get("rangeWithScores")).isNotNull();
144-
assertThat(result.get("reverseRangeWithScores")).isNotNull();
145-
assertThat(result.get("rangeByScoreWithScores")).isNotNull();
146-
assertThat(result.get("reverseRangeByScoreWithScores")).isNotNull();
166+
// add result is null (no result until exec)
167+
assertThat(result).containsEntry("add_result", null);
168+
169+
// before: only data added outside transaction is visible
170+
assertThat((Set<TypedTuple<String>>) result.get("rangeWithScores_before"))
171+
.hasSize(2)
172+
.extracting(TypedTuple::getValue)
173+
.containsExactly("outside1", "outside2");
174+
175+
assertThat((Set<TypedTuple<String>>) result.get("reverseRangeWithScores_before"))
176+
.hasSize(2)
177+
.extracting(TypedTuple::getValue)
178+
.containsExactly("outside2", "outside1");
179+
180+
assertThat((Set<TypedTuple<String>>) result.get("rangeByScoreWithScores_before"))
181+
.hasSize(2)
182+
.extracting(TypedTuple::getValue)
183+
.containsExactly("outside1", "outside2");
184+
185+
assertThat((Set<TypedTuple<String>>) result.get("reverseRangeByScoreWithScores_before"))
186+
.hasSize(2)
187+
.extracting(TypedTuple::getValue)
188+
.containsExactly("outside2", "outside1");
189+
190+
// after: changes made inside transaction are still not visible
191+
assertThat((Set<TypedTuple<String>>) result.get("rangeWithScores_after"))
192+
.hasSize(2)
193+
.extracting(TypedTuple::getValue)
194+
.containsExactly("outside1", "outside2");
195+
196+
assertThat((Set<TypedTuple<String>>) result.get("reverseRangeWithScores_after"))
197+
.hasSize(2)
198+
.extracting(TypedTuple::getValue)
199+
.containsExactly("outside2", "outside1");
200+
201+
assertThat((Set<TypedTuple<String>>) result.get("rangeByScoreWithScores_after"))
202+
.hasSize(2)
203+
.extracting(TypedTuple::getValue)
204+
.containsExactly("outside1", "outside2");
205+
206+
assertThat((Set<TypedTuple<String>>) result.get("reverseRangeByScoreWithScores_after"))
207+
.hasSize(2)
208+
.extracting(TypedTuple::getValue)
209+
.containsExactly("outside2", "outside1");
147210
}
148211

149212
static Stream<Arguments> argumentsStream() {

0 commit comments

Comments
 (0)