1
+ /*
2
+ * Copyright 2024 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
+ */
1
16
package org .springframework .data .redis .core ;
2
17
3
- import org .junit .jupiter .api .BeforeEach ;
18
+ import static org .assertj .core .api .Assertions .assertThat ;
19
+ import static org .mockito .ArgumentMatchers .any ;
20
+ import static org .mockito .ArgumentMatchers .eq ;
21
+ import static org .mockito .Mockito .times ;
22
+ import static org .mockito .Mockito .verify ;
23
+ import static org .mockito .Mockito .when ;
24
+
25
+ import java .util .ArrayList ;
26
+ import java .util .List ;
27
+
4
28
import org .junit .jupiter .api .Test ;
5
29
import org .junit .jupiter .api .extension .ExtendWith ;
6
30
import org .mockito .Mock ;
7
- import org .mockito .MockitoAnnotations ;
31
+ import org .mockito .Mockito ;
8
32
import org .mockito .junit .jupiter .MockitoExtension ;
9
33
import org .mockito .junit .jupiter .MockitoSettings ;
10
34
import org .mockito .quality .Strictness ;
11
- import org .springframework .context .ApplicationEvent ;
12
- import org .springframework .context .ApplicationEventPublisher ;
13
35
import org .springframework .core .convert .ConversionService ;
14
36
import org .springframework .data .redis .connection .Message ;
15
37
import org .springframework .data .redis .core .convert .RedisConverter ;
16
38
import org .springframework .data .redis .listener .RedisMessageListenerContainer ;
17
39
18
- import java .util .ArrayList ;
19
- import java .util .List ;
20
-
21
- import static org .assertj .core .api .Assertions .assertThat ;
22
- import static org .mockito .ArgumentMatchers .any ;
23
- import static org .mockito .Mockito .*;
24
40
/**
25
41
* @author Lucian Torje
42
+ * @author Christoph Strobl
26
43
*/
27
44
@ ExtendWith (MockitoExtension .class )
28
45
@ MockitoSettings (strictness = Strictness .LENIENT )
29
46
class MappingExpirationListenerTest {
30
47
31
- @ Mock
32
- private RedisOperations <?, ?> redisOperations ;
33
- @ Mock
34
- private RedisConverter redisConverter ;
35
- @ Mock
36
- private RedisMessageListenerContainer listenerContainer ;
37
- @ Mock
38
- private Message message ;
39
- @ Mock
40
- private RedisKeyExpiredEvent <?> event ;
41
- @ Mock
42
- private ConversionService conversionService ;
43
-
44
- private RedisKeyValueAdapter .MappingExpirationListener listener ;
45
-
46
- @ Test
47
- void testOnNonKeyExpiration () {
48
- byte [] key = "testKey" .getBytes ();
49
- when (message .getBody ()).thenReturn (key );
50
- listener = new RedisKeyValueAdapter .MappingExpirationListener (listenerContainer , redisOperations , redisConverter , RedisKeyValueAdapter .ShadowCopy .ON );
51
-
52
- listener .onMessage (message , null );
53
-
54
- verify (redisOperations , times (0 )).execute (any (RedisCallback .class ));
55
- }
56
-
57
- @ Test
58
- void testOnValidKeyExpiration () {
59
- List <Object > eventList = new ArrayList <>();
60
-
61
- byte [] key = "abc:testKey" .getBytes ();
62
- when (message .getBody ()).thenReturn (key );
63
-
64
- listener = new RedisKeyValueAdapter .MappingExpirationListener (listenerContainer , redisOperations , redisConverter , RedisKeyValueAdapter .ShadowCopy .OFF );
65
- listener .setApplicationEventPublisher (eventList ::add );
66
- listener .onMessage (message , null );
67
-
68
- verify (redisOperations , times (1 )).execute (any (RedisCallback .class ));
69
- assertThat (eventList ).hasSize (1 );
70
- assertThat (eventList .get (0 )).isInstanceOf (RedisKeyExpiredEvent .class );
71
- assertThat (((RedisKeyExpiredEvent ) (eventList .get (0 ))).getKeyspace ()).isEqualTo ("abc" );
72
- assertThat (((RedisKeyExpiredEvent ) (eventList .get (0 ))).getId ()).isEqualTo ("testKey" .getBytes ());
73
- }
74
- }
48
+ @ Mock private RedisOperations <?, ?> redisOperations ;
49
+ @ Mock private RedisConverter redisConverter ;
50
+ @ Mock private RedisMessageListenerContainer listenerContainer ;
51
+ @ Mock private Message message ;
52
+
53
+ private RedisKeyValueAdapter .MappingExpirationListener listener ;
54
+
55
+ @ Test // GH-2954
56
+ void testOnNonKeyExpiration () {
57
+
58
+ byte [] key = "testKey" .getBytes ();
59
+ when (message .getBody ()).thenReturn (key );
60
+ listener = new RedisKeyValueAdapter .MappingExpirationListener (listenerContainer , redisOperations , redisConverter ,
61
+ RedisKeyValueAdapter .ShadowCopy .ON );
62
+
63
+ listener .onMessage (message , null );
64
+
65
+ verify (redisOperations , times (0 )).execute (any (RedisCallback .class ));
66
+ }
67
+
68
+ @ Test // GH-2954
69
+ void testOnValidKeyExpirationWithShadowCopiesDisabled () {
70
+
71
+ List <Object > eventList = new ArrayList <>();
72
+
73
+ byte [] key = "abc:testKey" .getBytes ();
74
+ when (message .getBody ()).thenReturn (key );
75
+
76
+ listener = new RedisKeyValueAdapter .MappingExpirationListener (listenerContainer , redisOperations , redisConverter ,
77
+ RedisKeyValueAdapter .ShadowCopy .OFF );
78
+ listener .setApplicationEventPublisher (eventList ::add );
79
+ listener .onMessage (message , null );
80
+
81
+ verify (redisOperations , times (1 )).execute (any (RedisCallback .class ));
82
+ assertThat (eventList ).hasSize (1 );
83
+ assertThat (eventList .get (0 )).isInstanceOf (RedisKeyExpiredEvent .class );
84
+ assertThat (((RedisKeyExpiredEvent ) (eventList .get (0 ))).getKeyspace ()).isEqualTo ("abc" );
85
+ assertThat (((RedisKeyExpiredEvent ) (eventList .get (0 ))).getId ()).isEqualTo ("testKey" .getBytes ());
86
+ }
87
+
88
+ @ Test // GH-2954
89
+ void testOnValidKeyExpirationWithShadowCopiesEnabled () {
90
+
91
+ ConversionService conversionService = Mockito .mock (ConversionService .class );
92
+ List <Object > eventList = new ArrayList <>();
93
+
94
+ byte [] key = "abc:testKey" .getBytes ();
95
+ when (message .getBody ()).thenReturn (key );
96
+ when (redisConverter .getConversionService ()).thenReturn (conversionService );
97
+ when (conversionService .convert (any (), eq (byte [].class ))).thenReturn ("foo" .getBytes ());
98
+
99
+ listener = new RedisKeyValueAdapter .MappingExpirationListener (listenerContainer , redisOperations , redisConverter ,
100
+ RedisKeyValueAdapter .ShadowCopy .ON );
101
+ listener .setApplicationEventPublisher (eventList ::add );
102
+ listener .onMessage (message , null );
103
+
104
+ verify (redisOperations , times (2 )).execute (any (RedisCallback .class )); // delete entry in index, delete phantom key
105
+ assertThat (eventList ).hasSize (1 );
106
+ assertThat (eventList .get (0 )).isInstanceOf (RedisKeyExpiredEvent .class );
107
+ assertThat (((RedisKeyExpiredEvent ) (eventList .get (0 ))).getKeyspace ()).isEqualTo ("abc" );
108
+ assertThat (((RedisKeyExpiredEvent ) (eventList .get (0 ))).getId ()).isEqualTo ("testKey" .getBytes ());
109
+ }
110
+ }
0 commit comments