View Javadoc
1   package guru.mikelue.jdut.example;
2   
3   import java.sql.Date;
4   import java.sql.SQLException;
5   import java.time.LocalDate;
6   import java.util.HashMap;
7   import java.util.Map;
8   import java.util.function.Supplier;
9   
10  import org.apache.commons.lang3.RandomUtils;
11  import org.junit.jupiter.api.AfterEach;
12  import org.junit.jupiter.api.BeforeAll;
13  import org.junit.jupiter.api.BeforeEach;
14  import org.junit.jupiter.api.Test;
15  import org.junit.jupiter.api.TestInfo;
16  
17  import guru.mikelue.jdut.DataConductor;
18  import guru.mikelue.jdut.annotation.IfDatabaseVendor;
19  import guru.mikelue.jdut.assertion.ResultSetAssert;
20  import guru.mikelue.jdut.datagrain.DataGrain;
21  import guru.mikelue.jdut.jdbc.JdbcTemplateFactory;
22  import guru.mikelue.jdut.jdbc.function.DbResultSet;
23  import guru.mikelue.jdut.operation.DefaultOperatorFactory;
24  import guru.mikelue.jdut.operation.DefaultOperators;
25  import guru.mikelue.jdut.operation.OperatorFactory;
26  import guru.mikelue.jdut.test.AbstractDataSourceTestBase;
27  import guru.mikelue.jdut.vendor.DatabaseVendor;
28  
29  import static org.junit.jupiter.api.Assertions.*;
30  
31  /**
32   * This example demonstrates the usage of JDUT by pure JDBC.
33   */
34  @IfDatabaseVendor(match=DatabaseVendor.H2)
35  public class JdbcExampleTest extends AbstractDataSourceTestBase {
36  	private static ExampleDao testedDao;
37  	private static DataConductor dataConductor;
38  	private static OperatorFactory operatorFactory;
39  
40  	private final String INSERT_ARTIST_NAME = "Miles Davis";
41  	private final String UPDATE_ARTIST_NAME = "John Coltrane";
42  	private final String REMOVE_ARTIST_NAME = "Blue Mountain";
43  
44  	private DataGrain dataGrainForUpdate;
45  
46  	private DataGrain dataGrain_1ForListing;
47  	private DataGrain dataGrain_2ForListing;
48  
49  	private Map<String, Runnable> setupFunctions = new HashMap<>();
50  	private Map<String, Runnable> tearDownFunctions = new HashMap<>();
51  
52  	public JdbcExampleTest()
53  	{
54  		setupFunctions.put("updateArtistName", this::setupUpdateArtistName);
55  		tearDownFunctions.put("updateArtistName", this::tearDownUpdateArtistName);
56  
57  		setupFunctions.put("countAlbumsByType", this::setupCountAlbumsByType);
58  		tearDownFunctions.put("countAlbumsByType", this::tearDownCountAlbumsByType);
59  
60  		setupFunctions.put("removeArtistByName", this::setupRemoveArtistByName);
61  
62  		tearDownFunctions.put("addArtist", this::tearDownAddArtist);
63  	}
64  
65  	@BeforeAll
66  	void setupDatabaseSchema()
67  	{
68  		SchemaSetup.buildSchema(getDataSource());
69  
70  		testedDao = new ExampleDao(getDataSource());
71  
72  		dataConductor = new DataConductor(getDataSource());
73  		operatorFactory = DefaultOperatorFactory.build(getDataSource());
74  	}
75  
76  	@BeforeEach
77  	void setupTest(TestInfo testInfo)
78  	{
79  		runByMethodName(testInfo, setupFunctions);
80  	}
81  	@AfterEach
82  	void tearDownTest(TestInfo testInfo)
83  	{
84  		runByMethodName(testInfo, tearDownFunctions);
85  	}
86  
87  	private void runByMethodName(TestInfo testInfo, Map<String, Runnable> funcs)
88  	{
89  		Runnable r = funcs.get(
90  			testInfo.getTestMethod().get().getName()
91  		);
92  
93  		if (r != null) {
94  			r.run();
95  		}
96  	}
97  
98  	@Test
99  	void addArtist() throws SQLException
100 	{
101 		testedDao.addArtist(INSERT_ARTIST_NAME);
102 
103 		JdbcTemplateFactory.buildRunnable(
104 			() -> getDataSource().getConnection(),
105 			conn -> DbResultSet.buildRunnable(
106 				conn,
107 				"SELECT COUNT(*) FROM ex_artist WHERE at_name = '" + INSERT_ARTIST_NAME + "'",
108 				rs -> new ResultSetAssert(rs)
109 					.assertNextTrue()
110 					.assertInt(1, 1)
111 			).runJdbc()
112 		).runJdbc();
113 	}
114 	private void tearDownAddArtist()
115 	{
116 		dataConductor.conduct(
117 			DataGrain.build(
118 				builder ->
119 					builder.name("ex_artist").keys("at_name"),
120 				rowsBuilder -> rowsBuilder
121 					.addFields(rowsBuilder.newField("at_name", INSERT_ARTIST_NAME))
122 			),
123 			operatorFactory.get(DefaultOperators.DELETE)
124 		);
125 	}
126 
127 	/**
128 	 * Tests the updating of data for artist.
129 	 */
130 	@Test
131 	void updateArtistName() throws SQLException
132 	{
133 		testedDao.updateArtistName(1001, UPDATE_ARTIST_NAME);
134 
135 		JdbcTemplateFactory.buildRunnable(
136 			() -> getDataSource().getConnection(),
137 			conn -> DbResultSet.buildRunnable(
138 				conn,
139 				"SELECT COUNT(*) FROM ex_artist WHERE at_name = '" + UPDATE_ARTIST_NAME + "'",
140 				rs -> new ResultSetAssert(rs)
141 					.assertNextTrue()
142 					.assertInt(1, 1)
143 			).runJdbc()
144 		).runJdbc();
145 	}
146 	private void setupUpdateArtistName()
147 	{
148 		dataGrainForUpdate = DataGrain.build(
149 			builder ->
150 				builder.name("ex_artist"),
151 			rowsBuilder -> rowsBuilder
152 				.implicitColumns("at_id", "at_name")
153 				.addValues(
154 					1001, "Dizzy Gillespie"
155 				)
156 		);
157 
158 		dataConductor.conduct(
159 			dataGrainForUpdate,
160 			operatorFactory.get(DefaultOperators.REFRESH)
161 		);
162 	}
163 	private void tearDownUpdateArtistName()
164 	{
165 		dataConductor.conduct(
166 			dataGrainForUpdate,
167 			operatorFactory.get(DefaultOperators.DELETE)
168 		);
169 	}
170 
171 	@Test
172 	void removeArtistByName() throws SQLException
173 	{
174 		testedDao.removeArtistByName(REMOVE_ARTIST_NAME);
175 
176 		JdbcTemplateFactory.buildRunnable(
177 			() -> getDataSource().getConnection(),
178 			conn -> DbResultSet.buildRunnable(
179 				conn,
180 				"SELECT COUNT(*) FROM ex_artist WHERE at_name = '" + REMOVE_ARTIST_NAME + "'",
181 				rs -> new ResultSetAssert(rs)
182 					.assertNextTrue()
183 					.assertInt(1, 0)
184 			).runJdbc()
185 		).runJdbc();
186 	}
187 	private void setupRemoveArtistByName()
188 	{
189 		dataConductor.conduct(
190 			DataGrain.build(
191 				builder -> builder.name("ex_artist"),
192 				rowsBuilder -> rowsBuilder
193 					.addFields(
194 						rowsBuilder.newField("at_name", REMOVE_ARTIST_NAME)
195 					)
196 			),
197 			operatorFactory.get(DefaultOperators.INSERT)
198 		);
199 	}
200 
201 	@Test
202 	void countAlbumsByType() throws SQLException
203 	{
204 		assertEquals(
205 			2,
206 			testedDao.countAlbumsByType(1)
207 		);
208 	}
209 	private void setupCountAlbumsByType()
210 	{
211 		int idOfArtistForListing = 9081;
212 
213 		/**
214 		 * Random data supplier
215 		 */
216 		Supplier<Date> randomDate = JdbcExampleTest::randomDate;
217 		Supplier<Integer> randomDuration = JdbcExampleTest::randomDuration;
218 		// :~)
219 
220 		/**
221 		 * Insertion of data for table "ex_artist"
222 		 */
223 		dataConductor.conduct(
224 			dataGrain_1ForListing = DataGrain.build(
225 				builder -> builder.name("ex_artist"),
226 				rowsBuilder -> rowsBuilder
227 					.implicitColumns("at_id", "at_name")
228 					.addValues(idOfArtistForListing, "Sonny Rollins")
229 			),
230 			operatorFactory.get(DefaultOperators.INSERT)
231 		);
232 		// :~)
233 		/**
234 		 * Insertion of data for table "ex_album"
235 		 */
236 		dataConductor.conduct(
237 			dataGrain_2ForListing = DataGrain.build(
238 				builder -> builder.name("ex_album"),
239 				rowsBuilder -> rowsBuilder
240 					.implicitColumns(
241 						"ab_id", "ab_name", "ab_release_date", "ab_duration_seconds", "ab_type", "ab_at_id"
242 					)
243 					.addValues(
244 						4051, "No. 1", randomDate, randomDuration,
245 						1,
246 						idOfArtistForListing
247 					)
248 					.addValues(
249 						4052, "No. 2", randomDate, randomDuration,
250 						2,
251 						idOfArtistForListing
252 					)
253 					.addValues(
254 						4053, "No. 3", randomDate, randomDuration,
255 						3,
256 						idOfArtistForListing
257 					)
258 					.addValues(
259 						4054, "No. 4", randomDate, randomDuration,
260 						1,
261 						idOfArtistForListing
262 					)
263 			),
264 			operatorFactory.get(DefaultOperators.INSERT)
265 		);
266 		// :~)
267 	}
268 	private void tearDownCountAlbumsByType()
269 	{
270 		dataConductor.conduct(
271 			dataGrain_2ForListing,
272 			operatorFactory.get(DefaultOperators.DELETE)
273 		);
274 		dataConductor.conduct(
275 			dataGrain_1ForListing,
276 			operatorFactory.get(DefaultOperators.DELETE)
277 		);
278 	}
279 
280 	private static Date randomDate()
281 	{
282 		return Date.valueOf(
283 			LocalDate.of(
284 				RandomUtils.nextInt(1950, 1961),
285 				RandomUtils.nextInt(1, 13),
286 				RandomUtils.nextInt(1, 26)
287 			)
288 		);
289 	}
290 
291 	private static int randomDuration()
292 	{
293 		return RandomUtils.nextInt(1800, 10801);
294 	}
295 }