View Javadoc
1   /*
2    * Copyright 2010-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  package org.mybatis.spring.batch;
17  
18  import static org.junit.jupiter.api.Assertions.fail;
19  
20  import java.util.Arrays;
21  import java.util.Collections;
22  import java.util.List;
23  
24  import org.apache.ibatis.cursor.Cursor;
25  import org.apache.ibatis.session.ExecutorType;
26  import org.apache.ibatis.session.SqlSession;
27  import org.apache.ibatis.session.SqlSessionFactory;
28  import org.assertj.core.api.Assertions;
29  import org.junit.jupiter.api.Test;
30  import org.junit.jupiter.api.extension.ExtendWith;
31  import org.mockito.Mock;
32  import org.mockito.Mockito;
33  import org.mockito.junit.jupiter.MockitoExtension;
34  import org.springframework.batch.infrastructure.item.ExecutionContext;
35  import org.springframework.batch.infrastructure.item.ItemStreamException;
36  
37  /**
38   * Tests for {@link MyBatisCursorItemReader}.
39   */
40  @ExtendWith(MockitoExtension.class)
41  class MyBatisCursorItemReaderTest {
42  
43    @Mock
44    private SqlSessionFactory sqlSessionFactory;
45  
46    @Mock
47    private SqlSession sqlSession;
48  
49    @Mock
50    private Cursor<Object> cursor;
51  
52    @Test
53    void testCloseOnFailing() throws Exception {
54  
55      Mockito.when(this.sqlSessionFactory.openSession(ExecutorType.SIMPLE)).thenReturn(this.sqlSession);
56      Mockito.when(this.sqlSession.selectCursor("selectFoo", Collections.singletonMap("id", 1)))
57          .thenThrow(new RuntimeException("error."));
58  
59      var itemReader = new MyBatisCursorItemReader<Foo>();
60      itemReader.setSqlSessionFactory(this.sqlSessionFactory);
61      itemReader.setQueryId("selectFoo");
62      itemReader.setParameterValues(Collections.singletonMap("id", 1));
63      itemReader.afterPropertiesSet();
64  
65      var executionContext = new ExecutionContext();
66      try {
67        itemReader.open(executionContext);
68        fail();
69      } catch (ItemStreamException e) {
70        Assertions.assertThat(e).hasMessage("Failed to initialize the reader").hasCause(new RuntimeException("error."));
71      } finally {
72        itemReader.close();
73        Mockito.verify(this.sqlSession).close();
74      }
75  
76    }
77  
78    @Test
79    void testCloseBeforeOpen() {
80      var itemReader = new MyBatisCursorItemReader<Foo>();
81      itemReader.close();
82    }
83  
84    private List<Object> getFoos() {
85      return Arrays.asList(new Foo("foo1"), new Foo("foo2"), new Foo("foo3"));
86    }
87  
88    // Note: Do not cleanup this 'foo' class
89    private static class Foo {
90      private final String name;
91  
92      Foo(String name) {
93        this.name = name;
94      }
95  
96      public String getName() {
97        return this.name;
98      }
99    }
100 
101 }