1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.dbunit.operation;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.atMost;
27 import static org.mockito.Mockito.doThrow;
28 import static org.mockito.Mockito.verify;
29
30 import java.io.Reader;
31 import java.nio.charset.StandardCharsets;
32 import java.nio.file.Files;
33 import java.sql.Connection;
34 import java.sql.SQLException;
35
36 import org.dbunit.AbstractDatabaseIT;
37 import org.dbunit.DatabaseUnitException;
38 import org.dbunit.TestFeature;
39 import org.dbunit.database.IDatabaseConnection;
40 import org.dbunit.dataset.IDataSet;
41 import org.dbunit.dataset.ITable;
42 import org.dbunit.dataset.xml.XmlDataSet;
43 import org.dbunit.testutil.TestUtils;
44 import org.junit.jupiter.api.Assumptions;
45 import org.junit.jupiter.api.BeforeEach;
46 import org.junit.jupiter.api.Test;
47 import org.junit.jupiter.api.extension.ExtendWith;
48 import org.mockito.Mock;
49 import org.mockito.junit.jupiter.MockitoExtension;
50
51
52
53
54
55
56 @ExtendWith(MockitoExtension.class)
57 class TransactionOperationIT extends AbstractDatabaseIT
58 {
59
60 @Mock
61 private IDatabaseConnection connection;
62
63 @Mock
64 private DatabaseOperation mockOperation;
65
66 @BeforeEach
67 void assumeTransactionsSupported()
68 {
69 Assumptions.assumeTrue(environmentHasFeature(TestFeature.TRANSACTION),
70 "Skip: database profile does not support transactions.");
71 }
72
73 @Test
74 void testExecute_withSuccessfulOperation_commitsAndRestoresAutoCommit() throws Exception
75 {
76 final String tableName = "TEST_TABLE";
77 final Reader in = Files.newBufferedReader(
78 TestUtils.getFile("xml/transactionOperationTest.xml").toPath(), StandardCharsets.UTF_8);
79 final IDataSet xmlDataSet = new XmlDataSet(in);
80 final Connection jdbcConnection = _connection.getConnection();
81
82 final ITable tableBefore =
83 _connection.createDataSet().getTable(tableName);
84 assertThat(tableBefore.getRowCount()).as("before row count")
85 .isEqualTo(6);
86 assertThat(jdbcConnection.getAutoCommit()).as("autocommit before")
87 .isTrue();
88
89 DatabaseOperation operation = new CompositeOperation(
90 DatabaseOperation.DELETE_ALL, DatabaseOperation.INSERT);
91 operation = new TransactionOperation(operation);
92 operation.execute(_connection, xmlDataSet);
93
94
95 final ITable tableAfter =
96 _connection.createDataSet().getTable(tableName);
97 assertThat(tableAfter.getRowCount()).as("after row count").isEqualTo(1);
98 assertThat(jdbcConnection.getAutoCommit()).as("autocommit after")
99 .isTrue();
100 }
101
102 @Test
103 void testExecute_withExistingTransaction_throwsExclusiveTransactionException() throws Exception
104 {
105 final String tableName = "TEST_TABLE";
106 final Reader in = Files.newBufferedReader(
107 TestUtils.getFile("xml/transactionOperationTest.xml").toPath(), StandardCharsets.UTF_8);
108 final IDataSet xmlDataSet = new XmlDataSet(in);
109 final Connection jdbcConnection = _connection.getConnection();
110
111 jdbcConnection.setAutoCommit(false);
112
113
114 assertThat(jdbcConnection.getAutoCommit()).as("autocommit before")
115 .isFalse();
116 final ITable tableBefore =
117 _connection.createDataSet().getTable(tableName);
118 assertThat(tableBefore.getRowCount()).as("before exclusive")
119 .isEqualTo(6);
120
121 assertThrows(ExclusiveTransactionException.class, () -> {
122
123 final DatabaseOperation operation =
124 new TransactionOperation(DatabaseOperation.DELETE);
125 operation.execute(_connection, xmlDataSet);
126 }, "Should throw ExclusiveTransactionException");
127 jdbcConnection.setAutoCommit(true);
128
129
130 final ITable tableAfter =
131 _connection.createDataSet().getTable(tableName);
132 assertThat(tableAfter.getRowCount()).as("after").isEqualTo(6);
133 }
134
135 @Test
136 void testExecute_withFailingOperation_rollsBackAndRestoresAutoCommit() throws Exception
137 {
138 final String tableName = "TEST_TABLE";
139 final Reader in = Files.newBufferedReader(
140 TestUtils.getFile("xml/transactionOperationTest.xml").toPath(), StandardCharsets.UTF_8);
141 final IDataSet xmlDataSet = new XmlDataSet(in);
142 final Exception[] exceptions = new Exception[] {new SQLException(),
143 new DatabaseUnitException(), new RuntimeException(),};
144 final Connection jdbcConnection = _connection.getConnection();
145
146 for (int i = 0; i < exceptions.length; i++)
147 {
148
149
150 final ITable tableBefore =
151 _connection.createDataSet().getTable(tableName);
152 assertThat(tableBefore.getRowCount()).as("before row count")
153 .isEqualTo(6);
154 assertThat(jdbcConnection.getAutoCommit()).as("autocommit before")
155 .isTrue();
156
157 doThrow(exceptions[i]).when(mockOperation).execute(any(), any());
158 assertThrows(Exception.class, () -> {
159 DatabaseOperation operation = new CompositeOperation(
160 DatabaseOperation.DELETE_ALL, mockOperation);
161 operation = new TransactionOperation(operation);
162 operation.execute(_connection, xmlDataSet);
163 }, "Should throw an exception");
164
165 verify(mockOperation, atMost(3)).execute(any(), any());
166
167
168 final ITable tableAfter =
169 _connection.createDataSet().getTable(tableName);
170 assertThat(tableAfter.getRowCount()).as("after row count")
171 .isEqualTo(6);
172 assertThat(jdbcConnection.getAutoCommit()).as("autocommit after")
173 .isTrue();
174
175 }
176 }
177 }