29
29
import static org .mockito .Mockito .never ;
30
30
import static org .mockito .Mockito .times ;
31
31
import static org .mockito .Mockito .verify ;
32
+ import static org .mockito .Mockito .verifyNoMoreInteractions ;
32
33
34
+ import java .util .ArrayList ;
33
35
import java .util .Arrays ;
34
36
import java .util .Collection ;
35
37
import java .util .Collections ;
67
69
import org .springframework .kafka .core .ProducerFactoryUtils ;
68
70
import org .springframework .kafka .listener .config .ContainerProperties ;
69
71
import org .springframework .kafka .support .TopicPartitionInitialOffset ;
72
+ import org .springframework .kafka .support .TransactionSupport ;
70
73
import org .springframework .kafka .test .rule .KafkaEmbedded ;
71
74
import org .springframework .kafka .test .utils .KafkaTestUtils ;
72
75
import org .springframework .kafka .transaction .KafkaTransactionManager ;
@@ -132,14 +135,18 @@ private void testConsumeAndProduceTransactionGuts(boolean chained, boolean handl
132
135
ConsumerFactory cf = mock (ConsumerFactory .class );
133
136
willReturn (consumer ).given (cf ).createConsumer ("group" , null );
134
137
Producer producer = mock (Producer .class );
135
- final CountDownLatch closeLatch = new CountDownLatch (1 );
138
+ final CountDownLatch closeLatch = new CountDownLatch (2 );
136
139
willAnswer (i -> {
137
140
closeLatch .countDown ();
138
141
return null ;
139
142
}).given (producer ).close ();
140
143
ProducerFactory pf = mock (ProducerFactory .class );
141
144
given (pf .transactionCapable ()).willReturn (true );
142
- given (pf .createProducer ()).willReturn (producer );
145
+ final List <String > transactionalIds = new ArrayList <>();
146
+ willAnswer (i -> {
147
+ transactionalIds .add (TransactionSupport .getTransactionIdSuffix ());
148
+ return producer ;
149
+ }).given (pf ).createProducer ();
143
150
KafkaTransactionManager tm = new KafkaTransactionManager (pf );
144
151
ContainerProperties props = new ContainerProperties ("foo" );
145
152
props .setGroupId ("group" );
@@ -161,6 +168,11 @@ private void testConsumeAndProduceTransactionGuts(boolean chained, boolean handl
161
168
assertThat (closeLatch .await (10 , TimeUnit .SECONDS )).isTrue ();
162
169
InOrder inOrder = inOrder (producer );
163
170
inOrder .verify (producer ).beginTransaction ();
171
+ inOrder .verify (producer ).sendOffsetsToTransaction (Collections .singletonMap (topicPartition ,
172
+ new OffsetAndMetadata (0 )), "group" );
173
+ inOrder .verify (producer ).commitTransaction ();
174
+ inOrder .verify (producer ).close ();
175
+ inOrder .verify (producer ).beginTransaction ();
164
176
ArgumentCaptor <ProducerRecord > captor = ArgumentCaptor .forClass (ProducerRecord .class );
165
177
inOrder .verify (producer ).send (captor .capture (), any (Callback .class ));
166
178
assertThat (captor .getValue ()).isEqualTo (new ProducerRecord ("bar" , "baz" ));
@@ -169,7 +181,10 @@ private void testConsumeAndProduceTransactionGuts(boolean chained, boolean handl
169
181
inOrder .verify (producer ).commitTransaction ();
170
182
inOrder .verify (producer ).close ();
171
183
container .stop ();
172
- verify (pf , times (1 )).createProducer ();
184
+ verify (pf , times (2 )).createProducer ();
185
+ verifyNoMoreInteractions (producer );
186
+ assertThat (transactionalIds .get (0 )).isEqualTo ("group.foo.0" );
187
+ assertThat (transactionalIds .get (0 )).isEqualTo ("group.foo.0" );
173
188
}
174
189
175
190
@ SuppressWarnings ({ "rawtypes" , "unchecked" })
@@ -409,7 +424,7 @@ public void testRollbackRecord() throws Exception {
409
424
}
410
425
});
411
426
412
- @ SuppressWarnings ({ "rawtypes" , "unchecked" })
427
+ @ SuppressWarnings ({ "rawtypes" })
413
428
KafkaTransactionManager tm = new KafkaTransactionManager (pf );
414
429
containerProps .setTransactionManager (tm );
415
430
KafkaMessageListenerContainer <Integer , String > container =
0 commit comments