diff --git a/pom.xml b/pom.xml index 1e161c9daa..199c398c64 100644 --- a/pom.xml +++ b/pom.xml @@ -401,6 +401,12 @@ ${springframework.version} test + + org.dbunit + dbunit + 2.7.3 + test + org.mockito mockito-core diff --git a/src/test/java/org/openelisglobal/BaseWebContextSensitiveTest.java b/src/test/java/org/openelisglobal/BaseWebContextSensitiveTest.java index 98110befde..dae952e56b 100644 --- a/src/test/java/org/openelisglobal/BaseWebContextSensitiveTest.java +++ b/src/test/java/org/openelisglobal/BaseWebContextSensitiveTest.java @@ -4,31 +4,59 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; -import org.junit.runner.RunWith; +import java.io.InputStream; +import java.util.*; +import javax.sql.DataSource; +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.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.SpringJUnit4ClassRunner; +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; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; -@RunWith(SpringJUnit4ClassRunner.class) +@Transactional(propagation = Propagation.NOT_SUPPORTED) @ContextConfiguration(classes = { BaseTestConfig.class, AppTestConfig.class }) @WebAppConfiguration @TestPropertySource("classpath:common.properties") @ActiveProfiles("test") -public abstract class BaseWebContextSensitiveTest { +public abstract class BaseWebContextSensitiveTest extends AbstractTransactionalJUnit4SpringContextTests { @Autowired protected WebApplicationContext webApplicationContext; + @Autowired + private DataSource dataSource; + protected MockMvc mockMvc; - protected void setUp() { + private Map originalStateCache; + + private List tablesToRestore; + + protected BaseWebContextSensitiveTest() { + this.originalStateCache = new HashMap<>(); + this.tablesToRestore = new ArrayList<>(); + } + + protected BaseWebContextSensitiveTest(List tablesToRestore) { + this.originalStateCache = new HashMap<>(); + this.tablesToRestore = tablesToRestore != null ? tablesToRestore : new ArrayList<>(); + } + + protected void setUp() throws Exception { mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build(); } @@ -44,4 +72,107 @@ public T mapFromJson(String json, Class clazz) throws IOException { objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); return objectMapper.readValue(json, clazz); } + + /** + * Executes a dataset with state management - preserves and restores the + * original state of affected tables after execution. + */ + protected void executeDataSetWithStateManagement(String datasetFilename) throws Exception { + if (datasetFilename == null) { + throw new NullPointerException("Please provide test dataset file to execute!"); + } + + IDatabaseConnection connection = 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(); + + // Backup current state of affected tables + IDataSet currentState = connection.createDataSet(tableNames); + originalStateCache.put(Arrays.toString(tableNames), currentState); + tablesToRestore.add(tableNames); + + executeDataSet(datasetFilename); + } finally { + 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. + */ + 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(); + } + } + } } diff --git a/src/test/java/org/openelisglobal/dictionary/rest/controller/DictionaryMenuRestControllerTest.java b/src/test/java/org/openelisglobal/dictionary/rest/controller/DictionaryMenuRestControllerTest.java index 27b0cf13fe..15fc984a89 100644 --- a/src/test/java/org/openelisglobal/dictionary/rest/controller/DictionaryMenuRestControllerTest.java +++ b/src/test/java/org/openelisglobal/dictionary/rest/controller/DictionaryMenuRestControllerTest.java @@ -20,8 +20,10 @@ import org.openelisglobal.dictionarycategory.valueholder.DictionaryCategory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; +import org.springframework.test.annotation.Rollback; import org.springframework.test.web.servlet.MvcResult; +@Rollback public class DictionaryMenuRestControllerTest extends BaseWebContextSensitiveTest { @Autowired @@ -32,8 +34,9 @@ public class DictionaryMenuRestControllerTest extends BaseWebContextSensitiveTes @Before @Override - public void setUp() { + public void setUp() throws Exception { super.setUp(); + executeDataSetWithStateManagement("testdata/dictionary.xml"); } @Test @@ -47,9 +50,10 @@ public void getDictionaryMenuList_shouldReturnDictionaryMenu() throws Exception List menuList = Arrays.asList(super.mapFromJson(content, DictionaryMenuForm[].class)); assertThat(menuList.get(0).getMenuList().get(0).getId(), is("1")); assertThat(menuList.get(0).getMenuList().get(0).getIsActive(), is("Y")); - assertThat(menuList.get(0).getMenuList().get(0).getDictEntry(), is("INFLUENZA VIRUS A RNA DETECTED")); - assertThat(menuList.get(0).getMenuList().get(0).getSortOrder(), is(100)); - assertThat(menuList.get(0).getMenuList().get(0).getDictionaryCategory().getCategoryName(), is("CG")); + assertThat(menuList.get(0).getMenuList().get(0).getDictEntry(), is("Dictionary Entry 1")); + assertThat(menuList.get(0).getMenuList().get(0).getSortOrder(), is(1)); + assertThat(menuList.get(0).getMenuList().get(0).getDictionaryCategory().getCategoryName(), + is("Category Name 1")); } @Test @@ -64,26 +68,6 @@ public void fetchDictionaryCategories_shouldFetchDictionaryDescriptions() throws assertThat(menuList, notNullValue()); } - // TODO: To be looked into later - - // @Test - // public void createDictionary_shouldSuccessfullyCreateDictionary() throws - // Exception { - // Dictionary dictionary = createDictionaryObject(); - // String toJson = super.mapToJson(dictionary); - // - // MvcResult mvcResult = super.mockMvc.perform( - // post("/rest/dictionary") - // .accept(MediaType.APPLICATION_JSON_VALUE) - // .contentType(MediaType.APPLICATION_JSON_VALUE) - // .content(toJson)).andReturn(); - // - // int status = mvcResult.getResponse().getStatus(); - // assertEquals(201, status); - // String content = mvcResult.getResponse().getContentAsString(); - // assertEquals(content, "Dictionary created successfully"); - // } - @Test public void showDeleteDictionary_shouldSuccessfullyDeleteDictionary() throws Exception { MvcResult getMenu = super.mockMvc.perform(get("/rest/DictionaryMenu").accept(MediaType.APPLICATION_JSON_VALUE) diff --git a/src/test/java/org/openelisglobal/dictionary/service/DictionaryServiceTest.java b/src/test/java/org/openelisglobal/dictionary/service/DictionaryServiceTest.java new file mode 100644 index 0000000000..61becfe578 --- /dev/null +++ b/src/test/java/org/openelisglobal/dictionary/service/DictionaryServiceTest.java @@ -0,0 +1,193 @@ +package org.openelisglobal.dictionary.service; + +import java.util.List; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openelisglobal.BaseWebContextSensitiveTest; +import org.openelisglobal.dictionary.valueholder.Dictionary; +import org.openelisglobal.dictionarycategory.service.DictionaryCategoryService; +import org.openelisglobal.dictionarycategory.valueholder.DictionaryCategory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.Rollback; + +@Rollback +public class DictionaryServiceTest extends BaseWebContextSensitiveTest { + + @Autowired + DictionaryService dictionaryService; + + @Autowired + DictionaryCategoryService dictionaryCategoryService; + + @Before + public void setup() throws Exception { + executeDataSetWithStateManagement("testdata/dictionary.xml"); + } + + @Test + public void verifyTestData() { + List categories = dictionaryCategoryService.getAll(); + System.out.println("Dictionary Categories: " + categories.size()); + categories.forEach(cat -> System.out + .println(cat.getCategoryName() + " - " + cat.getLocalAbbreviation() + " - " + cat.getDescription())); + + List dictionaries = dictionaryService.getAll(); + System.out.println("Dictionaries: " + dictionaries.size()); + dictionaries.forEach(dict -> System.out.println(dict.getDictEntry() + " - " + dict.getIsActive())); + } + + @Test + public void delete_shouldDeleteDictionary() { + Dictionary dictionaryToDelete = dictionaryService.get("1"); + dictionaryToDelete.setSysUserId("admin"); + + Assert.assertNotNull(dictionaryToDelete); + + dictionaryService.delete(dictionaryToDelete); + Assert.assertEquals("N", dictionaryService.get("1").getIsActive()); + } + + @Test + public void getDictionaryEntriesByCategoryId_shouldReturnaListOfDictionaryEntriesByCategoryId() { + List dictionaries = dictionaryService.getDictionaryEntriesByCategoryId("1"); + Assert.assertNotEquals(0, dictionaries.size()); + + Assert.assertEquals("Dictionary Entry 1", dictionaries.get(0).getDictEntry()); + Assert.assertEquals("Y", dictionaries.get(0).getIsActive()); + Assert.assertEquals("DE1", dictionaries.get(0).getLocalAbbreviation()); + } + + @Test + public void getDictionaryByLocalAbbrev_shouldReturnDictionaryWhenGivenLocalAbbreviation() { + Dictionary dictionaryToGetByLocalAbbrev = dictionaryService.get("1"); + + Dictionary dictionary = dictionaryService.getDictionaryByLocalAbbrev(dictionaryToGetByLocalAbbrev); + + Assert.assertNotNull(dictionary); + Assert.assertEquals("Dictionary Entry 1", dictionary.getDictEntry()); + Assert.assertEquals("Y", dictionary.getIsActive()); + Assert.assertEquals("DE1", dictionary.getLocalAbbreviation()); + } + + @Test + public void getDictionaryByDictEntry_shouldReturnDictionaryWhenGivenDictEntry() { + Dictionary dictionary = dictionaryService.getDictionaryByDictEntry("Dictionary Entry 2"); + + Assert.assertNotNull(dictionary); + Assert.assertEquals("Y", dictionary.getIsActive()); + Assert.assertEquals("DE2", dictionary.getLocalAbbreviation()); + Assert.assertEquals("2", dictionary.getId()); + } + + @Test + public void getDictionaryById_shouldReturnDictionaryWhenGivenDictionaryId() { + Dictionary dictionary = dictionaryService.getDictionaryById("2"); + + Assert.assertNotNull(dictionary); + Assert.assertEquals("Dictionary Entry 2", dictionary.getDictEntry()); + Assert.assertEquals("DE2", dictionary.getLocalAbbreviation()); + Assert.assertEquals("2", dictionary.getId()); + Assert.assertEquals("Y", dictionary.getIsActive()); + } + +// @Test +// This fails with java.lang.AssertionError: Values should be different. Actual: 0 +// public void getDictionaryEntrysByCategoryAbbreviation_shouldGetDictEntrysByCategoryAbbreviation() { +// List dictionaries = dictionaryService.getDictionaryEntrysByCategoryAbbreviation("Dictionary", "CA2"); +// Assert.assertNotEquals(0, dictionaries.size()); +// +// Assert.assertEquals("Dictionary Entry 2", dictionaries.get(0).getDictEntry()); +// Assert.assertEquals("N", dictionaries.get(0).getIsActive()); +// Assert.assertEquals("DE2", dictionaries.get(0).getLocalAbbreviation()); +// } + + @Test + public void getDictionaryEntrysByNameAndCategoryDescription_shouldGetDictionaryEntrysByNameAndCategoryDescription() { + Dictionary dictionary = dictionaryService.getDictionaryEntrysByNameAndCategoryDescription("Dictionary Entry 1", + "Category Description 1"); + Assert.assertNotNull(dictionary); + + Assert.assertEquals("Dictionary Entry 1", dictionary.getDictEntry()); + Assert.assertEquals("Y", dictionary.getIsActive()); + Assert.assertEquals("DE1", dictionary.getLocalAbbreviation()); + } + + @Test + public void getDictionaryEntrysByCategoryNameLocalizedSort_shouldGetDictionaryEntrysByCategoryNameLocalizedSort() { + List dictionaries = dictionaryService + .getDictionaryEntrysByCategoryNameLocalizedSort("Category Name 1"); + Assert.assertNotEquals(0, dictionaries.size()); + + Assert.assertEquals("Dictionary Entry 1", dictionaries.get(0).getDictEntry()); + Assert.assertEquals("Y", dictionaries.get(0).getIsActive()); + Assert.assertEquals("DE1", dictionaries.get(0).getLocalAbbreviation()); + } + + @Test + public void getDataForId_shouldReturnDictionaryDataForTheProvidedDictionaryId() { + Dictionary dictionary = dictionaryService.getDataForId("1"); + + Assert.assertNotNull(dictionary); + Assert.assertEquals("Dictionary Entry 1", dictionary.getDictEntry()); + Assert.assertEquals("Y", dictionary.getIsActive()); + Assert.assertEquals("DE1", dictionary.getLocalAbbreviation()); + } + + @Test + public void getData_shouldReturnDictionaryDataForTheProvidedDictionaryId() { + Dictionary dictionaryToGet = dictionaryService.get("1"); + + dictionaryService.getData(dictionaryToGet); + + Assert.assertNotNull(dictionaryToGet); + Assert.assertEquals("Dictionary Entry 1", dictionaryToGet.getDictEntry()); + Assert.assertEquals("Y", dictionaryToGet.getIsActive()); + Assert.assertEquals("DE1", dictionaryToGet.getLocalAbbreviation()); + } + + @Test + public void getPagesOfSearchedDictionaries_shouldGetPagesOfSearchedDictionaries() { + List dictionaries = dictionaryService.getPagesOfSearchedDictionaries(1, "Dictionary Entry 1"); + + Assert.assertNotEquals(0, dictionaries.size()); + + Assert.assertEquals("Dictionary Entry 1", dictionaries.get(0).getDictEntry()); + Assert.assertEquals("Y", dictionaries.get(0).getIsActive()); + Assert.assertEquals("DE1", dictionaries.get(0).getLocalAbbreviation()); + } + + @Test + public void update_shouldUpdateDictionary() { + Dictionary dictionaryToUpdate = dictionaryService.get("1"); + dictionaryToUpdate.setDictEntry("INFLUENZA VIRUS A RNA DETECTEDetest"); + + Dictionary updatedDictionary = dictionaryService.update(dictionaryToUpdate); + Assert.assertNotNull(updatedDictionary); + + Assert.assertEquals("Y", dictionaryService.get("1").getIsActive()); + Assert.assertEquals("INFLUENZA VIRUS A RNA DETECTEDetest", dictionaryService.get("1").getDictEntry()); + } + + @Test + public void update_shouldUpdateDictionaryWhenDictionaryFrozenCheckIsRequired() { + Dictionary dictionaryToUpdate = dictionaryService.get("1"); + dictionaryToUpdate.setDictEntry("INFLUENZA VIRUS A RNA DETECTEDetest"); + + dictionaryService.update(dictionaryToUpdate, true); + + Assert.assertEquals("Y", dictionaryService.get("1").getIsActive()); + Assert.assertEquals("INFLUENZA VIRUS A RNA DETECTEDetest", dictionaryService.get("1").getDictEntry()); + } + + @Test + public void update_shouldUpdateDictionaryWhenDictionaryFrozenCheckIsNotRequired() { + Dictionary dictionaryToUpdate = dictionaryService.get("1"); + dictionaryToUpdate.setDictEntry("INFLUENZA VIRUS A RNA DETECTEDetest"); + + dictionaryService.update(dictionaryToUpdate, false); + + Assert.assertEquals("Y", dictionaryService.get("1").getIsActive()); + Assert.assertEquals("INFLUENZA VIRUS A RNA DETECTEDetest", dictionaryService.get("1").getDictEntry()); + } +} diff --git a/src/test/resources/testdata/dictionary.xml b/src/test/resources/testdata/dictionary.xml new file mode 100644 index 0000000000..72690054c4 --- /dev/null +++ b/src/test/resources/testdata/dictionary.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + +