Skip to content

Commit

Permalink
Merge pull request DIGI-UW#1445 from mherman22/improve-datasets-mgt
Browse files Browse the repository at this point in the history
(fix): Improve our dataset management for the integration tests
  • Loading branch information
mozzy11 authored Jan 28, 2025
2 parents 50a6522 + 4179d83 commit 6a8e237
Show file tree
Hide file tree
Showing 18 changed files with 759 additions and 1,787 deletions.
134 changes: 41 additions & 93 deletions src/test/java/org/openelisglobal/BaseWebContextSensitiveTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.transaction.AfterTransaction;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
Expand All @@ -34,6 +38,8 @@
@ActiveProfiles("test")
public abstract class BaseWebContextSensitiveTest extends AbstractTransactionalJUnit4SpringContextTests {

Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
protected WebApplicationContext webApplicationContext;

Expand All @@ -42,20 +48,6 @@ public abstract class BaseWebContextSensitiveTest extends AbstractTransactionalJ

protected MockMvc mockMvc;

private Map<String, IDataSet> originalStateCache;

private List<String[]> tablesToRestore;

protected BaseWebContextSensitiveTest() {
this.originalStateCache = new HashMap<>();
this.tablesToRestore = new ArrayList<>();
}

protected BaseWebContextSensitiveTest(List<String[]> tablesToRestore) {
this.originalStateCache = new HashMap<>();
this.tablesToRestore = tablesToRestore != null ? tablesToRestore : new ArrayList<>();
}

protected void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
}
Expand All @@ -74,104 +66,60 @@ public <T> T mapFromJson(String json, Class<T> clazz) throws IOException {
}

/**
* Executes a dataset with state management - preserves and restores the
* original state of affected tables after execution.
* Executes a database test with the specified dataset and sequence reset
* information.
*
* @param datasetFileName The filename of the dataset file in the classpath.
* @throws Exception If an error occurs while executing the test.
*/
protected void executeDataSetWithStateManagement(String datasetFilename) throws Exception {
if (datasetFilename == null) {
protected void executeDataSetWithStateManagement(String datasetFileName) throws Exception {
if (datasetFileName == null) {
throw new NullPointerException("Please provide test dataset file to execute!");
}

IDatabaseConnection connection = null;
InputStream inputStream = null;

try {
connection = new DatabaseConnection(dataSource.getConnection());
DatabaseConfig config = connection.getConfig();
config.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true);

IDataSet newDataSet = loadDataSet(datasetFilename);
String[] tableNames = newDataSet.getTableNames();
inputStream = getClass().getClassLoader().getResourceAsStream(datasetFileName);

// Backup current state of affected tables
IDataSet currentState = connection.createDataSet(tableNames);
originalStateCache.put(Arrays.toString(tableNames), currentState);
tablesToRestore.add(tableNames);
if (inputStream == null) {
throw new IllegalArgumentException("Dataset file '" + datasetFileName + "' not found in classpath");
}

executeDataSet(datasetFilename);
IDataSet dataset = new FlatXmlDataSet(inputStream);
String[] tableNames = dataset.getTableNames();
cleanRowsInCurrentConnection(tableNames);

DatabaseOperation.REFRESH.execute(connection, dataset);
} finally {
if (inputStream != null) {
inputStream.close();
}
if (connection != null) {
connection.close();
}
}
}

/**
* This method will be called after each transaction to restore the database
* state
*/
@AfterTransaction
@SuppressWarnings("unused")
protected void restoreDatabase() throws Exception {
try {
for (String[] tableNames : tablesToRestore) {
String key = Arrays.toString(tableNames);
IDataSet originalState = originalStateCache.get(key);
if (originalState != null) {
IDatabaseConnection connection = null;
try {
connection = new DatabaseConnection(dataSource.getConnection());
DatabaseConfig config = connection.getConfig();
config.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true);

DatabaseOperation.CLEAN_INSERT.execute(connection, originalState);
} finally {
if (connection != null) {
connection.close();
}
}
originalStateCache.remove(key);
}
}
} finally {
originalStateCache.clear();
tablesToRestore.clear();
}
}

/**
* Loads a dataset from an XML file.
*/
private IDataSet loadDataSet(String datasetFilename) throws Exception {
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(datasetFilename)) {
if (inputStream == null) {
throw new IllegalArgumentException("Dataset file '" + datasetFilename + "' not found in classpath");
}
return new FlatXmlDataSet(inputStream);
}
}

/**
* Executes a dataset from an XML file.
* Helper method to clear out all rows in specified tables within the given
* dataset in the current connection.
*
* @param tableNames The names of the tables to truncate.
* @throws SQLException If an error occurs during truncation.
*/
protected void executeDataSet(String datasetFilename) throws Exception {
if (datasetFilename == null) {
throw new NullPointerException("please provide test dataset file to execute!");
}

InputStream inputStream = getClass().getClassLoader().getResourceAsStream(datasetFilename);
try (inputStream) {
if (inputStream == null) {
throw new IllegalArgumentException("Dataset file '" + datasetFilename + "' not found in classpath");
}
IDatabaseConnection connection = new DatabaseConnection(dataSource.getConnection());

DatabaseConfig config = connection.getConfig();
config.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true);
IDataSet dataset = new FlatXmlDataSet(inputStream);

try {
DatabaseOperation.REFRESH.execute(connection, dataset);
} finally {
connection.close();
protected void cleanRowsInCurrentConnection(String[] tableNames) throws SQLException, DatabaseUnitException {
IDatabaseConnection connection = new DatabaseConnection(dataSource.getConnection());
try (Connection conn = connection.getConnection(); Statement stmt = conn.createStatement()) {
for (String tableName : tableNames) {
String truncateQuery = "TRUNCATE TABLE " + tableName + " RESTART IDENTITY CASCADE";
logger.info("Truncating table: {}", tableName);
stmt.execute(truncateQuery);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.openelisglobal.address;

import org.junit.After;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -15,92 +15,54 @@ public class AddressPartServiceTest extends BaseWebContextSensitiveTest {
AddressPartService partService;

@Before
public void init() {
partService.deleteAll(partService.getAll());
}

@After
public void tearDown() {
partService.deleteAll(partService.getAll());
public void init() throws Exception {
executeDataSetWithStateManagement("testdata/personaddress.xml");
}

@Test
public void createAddressPart_shouldCreateAddressPart() throws Exception {
AddressPart part = new AddressPart();
part.setPartName("PartName");
part.setDisplayOrder("022");

Assert.assertEquals(0, partService.getAll().size());

partService.save(part);

Assert.assertEquals(1, partService.getAll().size());
Assert.assertEquals("PartName", part.getPartName());
Assert.assertEquals("022", part.getDisplayOrder());
public void verifyTestData() {
List<AddressPart> addressPartList = partService.getAll();
System.out.println("address parts we have in db: " + addressPartList.size());
addressPartList.forEach(addressPart -> System.out.println(
addressPart.getId() + " - " + addressPart.getPartName() + " - " + addressPart.getDisplayOrder()));
}

@Test
public void getAll_shouldGetAllAddressParts() throws Exception {
AddressPart part = new AddressPart();
part.setPartName("PartName");
part.setDisplayOrder("022");

partService.save(part);

AddressPart part2 = new AddressPart();
part2.setPartName("PartName2");
part2.setDisplayOrder("023");

partService.save(part2);

Assert.assertEquals(2, partService.getAll().size());

Assert.assertEquals(3, partService.getAll().size());
}

@Test
public void updateAddressPart_shouldUpdateAddressPart() throws Exception {
public void createAddressPart_shouldCreateAddressPart() throws Exception {
AddressPart part = new AddressPart();
part.setPartName("PartName");
part.setDisplayOrder("022");

Assert.assertEquals(0, partService.getAll().size());

String partId = partService.insert(part);
AddressPart savedPart = partService.get(partId);
savedPart.setPartName("upadtedName");
partService.save(savedPart);

Assert.assertEquals("upadtedName", savedPart.getPartName());

partService.save(part);
Assert.assertEquals("PartName", part.getPartName());
Assert.assertEquals("022", part.getDisplayOrder());
}

@Test
public void deleteAddressPart_shouldDeleteAddressPart() throws Exception {
public void updateAddressPart_shouldUpdateAddressPart() {
AddressPart part = new AddressPart();
part.setPartName("PartName");
part.setDisplayOrder("022");

Assert.assertEquals(0, partService.getAll().size());

String partId = partService.insert(part);
AddressPart savedPart = partService.get(partId);
savedPart.setPartName("upadtedName");
partService.delete(savedPart);
savedPart.setPartName("updatedName");
partService.save(savedPart);

Assert.assertEquals(0, partService.getAll().size());
Assert.assertEquals("updatedName", savedPart.getPartName());

}

@Test
public void getAddressPartByNam_shouldReturnAddressPartByName() throws Exception {
AddressPart part = new AddressPart();
part.setPartName("PartName");
part.setDisplayOrder("022");

Assert.assertEquals(0, partService.getAll().size());
public void getAddressPartByNam_shouldReturnAddressPartByName() {
AddressPart part = partService.getAddresPartByName("Village");

partService.save(part);

Assert.assertEquals("022", part.getDisplayOrder());
Assert.assertEquals("Village", part.getPartName());
Assert.assertEquals("1", part.getDisplayOrder());
}
}
Loading

0 comments on commit 6a8e237

Please sign in to comment.