CollectionInConstructorTest.java
/*
* Copyright 2009-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.submitted.collection_in_constructor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import java.io.Reader;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.ibatis.BaseDataTest;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
class CollectionInConstructorTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeAll
static void setUp() throws Exception {
// create an SqlSessionFactory
try (Reader reader = Resources
.getResourceAsReader("org/apache/ibatis/submitted/collection_in_constructor/mybatis-config.xml")) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
// populate in-memory database
BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
"org/apache/ibatis/submitted/collection_in_constructor/CreateDB.sql");
}
@Test
void testSimple() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store store = mapper.getAStore(1);
List<Aisle> aisles = store.getAisles();
Assertions.assertIterableEquals(
Arrays.asList(new Aisle(101, "Aisle 101"), new Aisle(102, "Aisle 102"), new Aisle(103, "Aisle 103")), aisles);
}
}
@Test
void testSimpleList() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
List<Store> stores = mapper.getStores();
Assertions.assertIterableEquals(
Arrays.asList(new Aisle(101, "Aisle 101"), new Aisle(102, "Aisle 102"), new Aisle(103, "Aisle 103")),
stores.get(0).getAisles());
Assertions.assertTrue(stores.get(1).getAisles().isEmpty());
Assertions.assertIterableEquals(Arrays.asList(new Aisle(104, "Aisle 104"), new Aisle(105, "Aisle 105")),
stores.get(2).getAisles());
}
}
@Test
void shouldEmptyListBeReturned() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Assertions.assertTrue(mapper.getAStore(2).getAisles().isEmpty());
}
}
@Test
void testTwoLists() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store2 store = mapper.getAStore2(1);
List<Clerk> clerks = store.getClerks();
List<Aisle> aisles = store.getAisles();
Assertions.assertIterableEquals(Arrays.asList(new Clerk(1001, "Clerk 1001"), new Clerk(1002, "Clerk 1002"),
new Clerk(1003, "Clerk 1003"), new Clerk(1004, "Clerk 1004"), new Clerk(1005, "Clerk 1005")), clerks);
Assertions.assertIterableEquals(
Arrays.asList(new Aisle(101, "Aisle 101"), new Aisle(102, "Aisle 102"), new Aisle(103, "Aisle 103")), aisles);
}
}
@Test
void testListOfStrings() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store3 store = mapper.getAStore3(1);
List<String> aisleNames = store.getAisleNames();
Assertions.assertEquals(3, aisleNames.size());
Assertions.assertIterableEquals(Arrays.asList("Aisle 101", "Aisle 102", "Aisle 103"), aisleNames);
}
}
@Test
void testObjectWithBuilder() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store4 store = mapper.getAStore4(1);
List<Aisle> aisles = store.getAisles();
Assertions.assertIterableEquals(
Arrays.asList(new Aisle(101, "Aisle 101"), new Aisle(102, "Aisle 102"), new Aisle(103, "Aisle 103")), aisles);
}
}
@Test
void testTwoListsOfSameResultMap() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store5 store = mapper.getAStore5(1);
List<Clerk> clerks = store.getClerks();
List<Clerk> managers = store.getManagers();
Assertions.assertIterableEquals(Arrays.asList(new Clerk(1001, "Clerk 1001"), new Clerk(1002, "Clerk 1002"),
new Clerk(1003, "Clerk 1003"), new Clerk(1004, "Clerk 1004"), new Clerk(1005, "Clerk 1005")), clerks);
Assertions.assertIterableEquals(Arrays.asList(new Clerk(1002, "Clerk 1002"), new Clerk(1005, "Clerk 1005")),
managers);
}
}
@Disabled("Not sure if there is a need for this usage.")
@Test
void testPartiallyImmutableObject() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store6 store = mapper.getAStore6(1);
List<Aisle> aisles = store.getAisles();
Assertions.assertEquals("Store 1", store.getName());
Assertions.assertEquals(3, aisles.size());
}
}
@Test
void testTwoListsOfString() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store7 store = mapper.getAStore7(1);
List<String> aisleNames = store.getAisleNames();
List<String> clerkNames = store.getClerkNames();
Assertions.assertIterableEquals(Arrays.asList("Aisle 101", "Aisle 102", "Aisle 103"), aisleNames);
Assertions.assertIterableEquals(
Arrays.asList("Clerk 1001", "Clerk 1002", "Clerk 1003", "Clerk 1004", "Clerk 1005"), clerkNames);
}
}
@Test
void testCollectionArgWithTypeHandler() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Store8 store = mapper.getAStore8(1);
Assertions.assertIterableEquals(Arrays.asList("a", "b", "c"), store.getStrings());
}
}
@Test
void testCollectionArgWithNestedAndTypeHandler() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
List<Store10> stores10 = mapper.getStores10();
assertThat(stores10).isNotNull().hasSize(3)
.extracting(Store10::getId, Store10::getName, store -> store.getClerks().size(), Store10::getStrings)
.containsExactly(tuple(1, "Store 1", 5, List.of("a", "b", "c", "1")),
tuple(2, "Store 2", 0, List.of("a", "b", "c", "2")), tuple(3, "Store 3", 0, List.of("a", "b", "c", "3")));
assertThat(stores10.get(0).getClerks()).extracting(Clerk::getId, Clerk::getName).containsExactly(
tuple(1001, "Clerk 1001"), tuple(1002, "Clerk 1002"), tuple(1003, "Clerk 1003"), tuple(1004, "Clerk 1004"),
tuple(1005, "Clerk 1005"));
}
}
@Test
void testImmutableNestedObjects() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
Container container = mapper.getAContainer();
Assertions
.assertEquals(
Arrays.asList(
new Store(1, "Store 1",
Arrays.asList(new Aisle(101, "Aisle 101"), new Aisle(102, "Aisle 102"),
new Aisle(103, "Aisle 103"))),
new Store(2, "Store 2", Collections.emptyList()),
new Store(3, "Store 3", Arrays.asList(new Aisle(104, "Aisle 104"), new Aisle(105, "Aisle 105")))),
container.getStores());
}
}
@Test
void testImmutableNestedObjectsWithBadEquals() {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Mapper mapper = sqlSession.getMapper(Mapper.class);
List<Container1> containers = mapper.getContainers();
Container1 expectedContainer1 = new Container1();
expectedContainer1.setNum(1);
expectedContainer1.setType("storesWithClerks");
expectedContainer1.setStores(Arrays.asList(
new Store9(1, "Store 1",
Arrays.asList(new Clerk(1001, "Clerk 1001"), new Clerk(1003, "Clerk 1003"),
new Clerk(1004, "Clerk 1004"))),
new Store9(2, "Store 2", Arrays.asList()), new Store9(3, "Store 3", Arrays.asList())));
Container1 expectedContainer2 = new Container1();
expectedContainer2.setNum(1);
expectedContainer2.setType("storesWithManagers");
expectedContainer2.setStores(Arrays.asList(
new Store9(1, "Store 1", Arrays.asList(new Clerk(1002, "Clerk 1002"), new Clerk(1005, "Clerk 1005")))));
// cannot use direct equals as we overwrote it with a bad impl on purpose
assertThat(containers).isNotNull().hasSize(2);
assertContainer1(containers.get(0), expectedContainer1);
assertContainer1(containers.get(1), expectedContainer2);
}
}
private static void assertContainer1(Container1 container1, Container1 expectedContainer1) {
assertThat(container1).isNotNull().satisfies(c -> {
assertThat(c.getNum()).isEqualTo(expectedContainer1.getNum());
assertThat(c.getType()).isEqualTo(expectedContainer1.getType());
assertThat(c.getStores()).isEqualTo(expectedContainer1.getStores());
});
}
}