From a33763c936c4cb29f03d0565230903c8c9045e76 Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Sat, 16 Sep 2017 18:39:44 +0200 Subject: [PATCH 1/8] eclipse specific generated files/folders added to .gitignore --- .gitignore | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f1a9ec7..0d12dc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,12 @@ - +# general /target/ /TestDataLoader.iml + +# IDEA specific *.iml /.idea/ + +# eclipse specific +.classpath +.project +.settings/ From 0b4454491edc9737d7b72a957d777fe9710d84f8 Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Sat, 16 Sep 2017 21:22:13 +0200 Subject: [PATCH 2/8] Implemented ideas described in triologygmbh/test-data-loader#8 and triologygmbh/test-data-loader#9 --- .../blog/testdataloader/EntityBuilder.groovy | 146 ++---------------- .../testdataloader/EntityBuilderDsl.groovy | 107 +++++++++++++ .../testdataloader/EntityBuilderScript.groovy | 32 ++++ .../EntityCreatedListener.groovy | 5 +- .../blog/testdataloader/EntityDeleter.groovy | 13 +- .../testdataloader/EntityPersister.groovy | 7 +- .../blog/testdataloader/TestDataLoader.groovy | 82 +++++----- .../blog/testdataloader/EntityStore.java | 55 +++++++ .../testdataloader/EntityBuilderTest.java | 120 ++++++++------ .../testdataloader/EntityDeleterTest.java | 54 +++---- .../testdataloader/EntityPersisterTest.java | 14 +- src/test/resources/demo/testData.groovy | 1 - ...ingBecauseOfMissingReferencedEntity.groovy | 2 - .../tests/failingBecauseOfReusedName.groovy | 2 - .../resources/tests/mappedSuperclass.groovy | 2 - .../tests/testEntityDefinitions.groovy | 2 - ...fEntityCreatedListenerNotifications.groovy | 2 - 17 files changed, 366 insertions(+), 280 deletions(-) create mode 100755 src/main/groovy/de/triology/blog/testdataloader/EntityBuilderDsl.groovy create mode 100755 src/main/groovy/de/triology/blog/testdataloader/EntityBuilderScript.groovy create mode 100755 src/main/java/de/triology/blog/testdataloader/EntityStore.java diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilder.groovy b/src/main/groovy/de/triology/blog/testdataloader/EntityBuilder.groovy index 4db01fe..e459220 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilder.groovy +++ b/src/main/groovy/de/triology/blog/testdataloader/EntityBuilder.groovy @@ -23,7 +23,6 @@ */ package de.triology.blog.testdataloader -import groovy.transform.PackageScope import org.codehaus.groovy.control.CompilerConfiguration /** @@ -31,158 +30,47 @@ import org.codehaus.groovy.control.CompilerConfiguration */ class EntityBuilder { - private static EntityBuilder singletonInstance; - - private Map entitiesByName = [:] private List entityCreatedListeners = [] private EntityBuilder() {} - /** - * Gets the EntityBuilder singleton instance - * @return EntityBuilder - */ - protected static EntityBuilder instance() { - singletonInstance = singletonInstance ?: new EntityBuilder(); - return singletonInstance + public static EntityBuilder newBuilder() { + return new EntityBuilder() } + + /** * Builds the entities defined in the provided by the passed Reader. * * @param entityDefinitionReader Reader - a Reader for the file containing the entity definitions */ - protected void buildEntities(Reader entityDefinitionReader) { - DelegatingScript script = createExecutableScriptFromEntityDefinition(entityDefinitionReader) - script.setDelegate(this) - script.run() - } - - private DelegatingScript createExecutableScriptFromEntityDefinition(Reader entityDefinitionReader) { - GroovyShell shell = createGroovyShell() - return (DelegatingScript) shell.parse(entityDefinitionReader) - } - - private GroovyShell createGroovyShell() { + public EntityStore build(Reader entityDefinitionReader) { CompilerConfiguration compilerConfiguration = new CompilerConfiguration() - compilerConfiguration.scriptBaseClass = DelegatingScript.class.name - return new GroovyShell(this.class.classLoader, compilerConfiguration) - } + compilerConfiguration.scriptBaseClass = EntityBuilderScript.class.name - /** - * Creates an Instance of the specified entityClass, registers it under the specified entityName and applies the - * specified entityData definition - * - * @param entityClass - * @param entityName - * @param entityData - * @return the created entity - */ - static T create(@DelegatesTo.Target Class entityClass, String entityName, - @DelegatesTo(strategy = Closure.DELEGATE_FIRST, genericTypeIndex = 0) Closure entityData = {}) { - return instance().createEntity(entityClass, entityName, entityData); - } - - private T createEntity(Class entityClass, String entityName, Closure entityData) { - T entity = createEntityInstance(entityName, entityClass) - executeEntityDataDefinition(entityData, entity) - notifyEntityCreatedListeners(entity) - return entity - } - - private T createEntityInstance(String entityName, Class entityClass) { - ensureNameHasNotYetBeenAssigned(entityName, entityClass) - T entity = entityClass.newInstance() - entitiesByName[entityName] = entity; - return entity - } - - private void ensureNameHasNotYetBeenAssigned(String entityName, Class requestedEntityClass) { - if (entitiesByName[entityName]) { - throw new EntityBuildingException( - "attempt to create an instance of $requestedEntityClass under the name of '$entityName' but an " + - "entity with that name already exists: ${entitiesByName[entityName]}") - } - } - - private void notifyEntityCreatedListeners(Object entity) { - entityCreatedListeners.each { - it.entityCreated(entity) - } - } + EntityBuilderDsl dsl = new EntityBuilderDsl(this) + Binding binding = new Binding() + binding.dsl = dsl - private void executeEntityDataDefinition(Closure entityDataDefinition, Object entity) { - entityDataDefinition = entityDataDefinition.rehydrate(entity, this, this) - entityDataDefinition.call() - } + GroovyShell shell = new GroovyShell(this.class.classLoader, binding, compilerConfiguration) + Script script = shell.parse(entityDefinitionReader) + script.run() - /** - * Implementation of Groovy's {@code propertyMissing} that returns the entity previously created under the property - * name. This Method will be called during entity creation, when an entity is referenced. - * - * @param name String - * @return a previously created entity - */ - private def propertyMissing(String name) { - if (entitiesByName[name]) { - return entitiesByName[name] - } - throw new EntityBuildingException("requested reference for entity with name '$name' cannot be resolved") + return dsl } /** * Adds an {@link EntityCreatedListener} that gets notified every time an entity is completely created. * @param listener {@link EntityCreatedListener} */ - protected void addEntityCreatedListener(EntityCreatedListener listener) { + public EntityBuilder addEntityCreatedListener(EntityCreatedListener listener) { entityCreatedListeners += listener + return this } - /** - * Removes the {@link EntityCreatedListener} - * @param listener {@link EntityCreatedListener} - */ - protected void removeEntityCreatedListener(EntityCreatedListener listener) { - entityCreatedListeners -= listener - } - - /** - * Gets the entity with the specified name from the set of entities created. - * - * If this {@code EntityBuilder} has not created an entity by the passed name a {@link NoSuchElementException} is - * thrown. If an entity is found but has a different type than the passed {@code entityClass}, an - * {@link IllegalArgumentException} is thrown. - * - * @param name {@link String} - the requested entity's name - * @param entityClass the requested entity's {@link Class} - * @return the requested entity - */ - protected T getEntityByName(String name, Class entityClass) { - def entity = findEntity(name) - ensureTypesMatch(entityClass, entity, name) - return (T) entity; - } - - private Object findEntity(String name) { - def entity = entitiesByName[name] - if (!entity) { - throw new NoSuchElementException("an entity named '$name' has not been created by the EntityBuilder") - } - return entity - } - - private void ensureTypesMatch(Class entityClass, entity, String name) { - if (entityClass != entity.class) { - throw new IllegalArgumentException( - "The class of the requested entity named '$name' does not match the requested class. Requested: $entityClass, Actual: ${entity.class}") - } - } - - /** - * Clears all previously built entities. - */ - protected void clear() { - entitiesByName.clear() + protected void fireEntityCreated(String entityName, Object entity) { + entityCreatedListeners.each { it.onEntityCreated(entityName, entity) } } } diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderDsl.groovy b/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderDsl.groovy new file mode 100755 index 0000000..3317e56 --- /dev/null +++ b/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderDsl.groovy @@ -0,0 +1,107 @@ +/** + * MIT License + * + * Copyright (c) 2016 TRIOLOGY GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.triology.blog.testdataloader + +class EntityBuilderDsl implements EntityStore { + + private Map entitiesByName = [:] + private EntityBuilder builder; + + protected EntityBuilderDsl(EntityBuilder builder) { + this.builder = builder; + } + + /** + * Creates an Instance of the specified entityClass, registers it under the specified entityName and applies the + * specified entityData definition + * + * @param entityClass + * @param entityName + * @param entityData + * @return the created entity + */ + public T create(@DelegatesTo.Target Class entityClass, String entityName, + @DelegatesTo(strategy = Closure.DELEGATE_FIRST, genericTypeIndex = 0) Closure entityData = {}) { + T entity = createEntityInstance(entityName, entityClass) + executeEntityDataDefinition(entityData, entity) + builder.fireEntityCreated(entityName, entity) + return entity + } + + private T createEntityInstance(String entityName, Class entityClass) { + ensureNameHasNotYetBeenAssigned(entityName, entityClass) + T entity = entityClass.newInstance() + entitiesByName[entityName] = entity; + return entity + } + + private void ensureNameHasNotYetBeenAssigned(String entityName, Class requestedEntityClass) { + if (entitiesByName[entityName]) { + throw new EntityBuildingException( + "attempt to create an instance of $requestedEntityClass under the name of '$entityName' but an " + + "entity with that name already exists: ${entitiesByName[entityName]}") + } + } + + private void executeEntityDataDefinition(Closure entityDataDefinition, Object entity) { + entityDataDefinition = entityDataDefinition.rehydrate(entity, this, this) + entityDataDefinition.call() + } + + /** + * Implementation of Groovy's {@code propertyMissing} that returns the entity previously created under the property + * name. This Method will be called during entity creation, when an entity is referenced. + * + * @param name String + * @return a previously created entity + */ + private def propertyMissing(String name) { + if (entitiesByName[name]) { + return entitiesByName[name] + } + throw new EntityBuildingException("requested reference for entity with name '$name' cannot be resolved") + } + + + @Override + public T getEntityByName(String name, Class entityClass) { + def entity = entitiesByName[name] + if (!entity) { + throw new NoSuchElementException("an entity named '$name' has not been created by the EntityBuilder") + } + + if (entityClass != entity.class) { + throw new IllegalArgumentException( + "The class of the requested entity named '$name' does not match the requested class. Requested: $entityClass, Actual: ${entity.class}") + } + + return (T) entity; + } + + @Override + public void clear() { + entitiesByName.clear() + } +} diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderScript.groovy b/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderScript.groovy new file mode 100755 index 0000000..347ca48 --- /dev/null +++ b/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderScript.groovy @@ -0,0 +1,32 @@ +/** + * MIT License + * + * Copyright (c) 2016 TRIOLOGY GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.triology.blog.testdataloader + +abstract class EntityBuilderScript extends Script { + + @Delegate + @Lazy + EntityBuilderDsl dsl = this.binding.dsl +} diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityCreatedListener.groovy b/src/main/groovy/de/triology/blog/testdataloader/EntityCreatedListener.groovy index 10b6dfc..6bcbfc9 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityCreatedListener.groovy +++ b/src/main/groovy/de/triology/blog/testdataloader/EntityCreatedListener.groovy @@ -30,8 +30,9 @@ interface EntityCreatedListener { /** * Is called every time an entity is completely created, including all referenced entities. + * + * @param name the name of the entity created * @param entity the created entity */ - void entityCreated(Object entity) - + void onEntityCreated(String name, Object entity) } \ No newline at end of file diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityDeleter.groovy b/src/main/groovy/de/triology/blog/testdataloader/EntityDeleter.groovy index 01e209d..50f8aae 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityDeleter.groovy +++ b/src/main/groovy/de/triology/blog/testdataloader/EntityDeleter.groovy @@ -23,11 +23,12 @@ */ package de.triology.blog.testdataloader -import groovy.transform.PackageScope +import javax.persistence.EntityManager + import org.slf4j.Logger import org.slf4j.LoggerFactory -import javax.persistence.EntityManager +import groovy.transform.PackageScope /** * If added as {@link EntityCreatedListener} during entity creation, the EntityDeleter keeps track of created entities @@ -51,12 +52,8 @@ class EntityDeleter implements EntityCreatedListener { entities = new Stack() } - /** - * Keeps track of all created entities to be able to delete them later. - * - * @param entity a created entity - */ - public void entityCreated(Object entity) { + @Override + public void onEntityCreated(String name, Object entity) { entities.push(entity) } diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityPersister.groovy b/src/main/groovy/de/triology/blog/testdataloader/EntityPersister.groovy index 160655c..84ed379 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityPersister.groovy +++ b/src/main/groovy/de/triology/blog/testdataloader/EntityPersister.groovy @@ -36,11 +36,8 @@ class EntityPersister implements EntityCreatedListener { this.entityManager = entityManager } - /** - * Persists the passed entity using this instance's {@link javax.persistence.EntityManager}. - * @param entity - */ - void entityCreated(Object entity) { + @Override + void onEntityCreated(String name, Object entity) { entityManager.persist(entity) } } diff --git a/src/main/groovy/de/triology/blog/testdataloader/TestDataLoader.groovy b/src/main/groovy/de/triology/blog/testdataloader/TestDataLoader.groovy index 9da848a..c2f2a74 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/TestDataLoader.groovy +++ b/src/main/groovy/de/triology/blog/testdataloader/TestDataLoader.groovy @@ -23,16 +23,16 @@ */ package de.triology.blog.testdataloader +import javax.persistence.EntityManager + import org.slf4j.Logger import org.slf4j.LoggerFactory -import javax.persistence.EntityManager - /** * Loads test data from entity definition files, saves them to a database via a specified {@link EntityManager} and * makes the entities available by their names as defined in the entity definition files. */ -class TestDataLoader { +class TestDataLoader implements EntityStore, EntityCreatedListener { /** * Defines the transaction type that the {@link EntityManager} passed to the {@code TestDataLoader} is configured with. @@ -43,8 +43,11 @@ class TestDataLoader { private static final Logger LOG = LoggerFactory.getLogger(TestDataLoader) + private Map loadedEntities = [:].withDefault { + throw new NoSuchElementException("an entity named '$it' has not been created") + } + private EntityManager entityManager - private EntityBuilder entityBuilder private EntityDeleter entityDeleter private TransactionType transactionType; @@ -77,10 +80,11 @@ class TestDataLoader { * @param transactionType {@link TransactionType} */ TestDataLoader(EntityManager entityManager, TransactionType transactionType) { - if (transactionType == null) throw new IllegalArgumentException("transactionType must not be null") + if (transactionType == null) { + throw new IllegalArgumentException("transactionType must not be null") + } checkTransactionType(entityManager, transactionType) this.entityManager = entityManager - entityBuilder = EntityBuilder.instance() entityDeleter = new EntityDeleter(entityManager) this.transactionType = transactionType; } @@ -96,10 +100,10 @@ class TestDataLoader { entityManager.getTransaction() } catch (IllegalStateException e) { throw new IllegalStateException( - 'TestDataLoader is configured with RESOURCE_LOCAL transactions but the supplied EntityManager uses ' + - 'JTA transactions. Use the TestDataLoader#TestDataLoader(EntityManager, TransactionType) ' + - 'constructor to specify that JTA transactions are being used. Note that the client code ' + - 'needs to take care of transaction management in this case.', e) + 'TestDataLoader is configured with RESOURCE_LOCAL transactions but the supplied EntityManager uses ' + + 'JTA transactions. Use the TestDataLoader#TestDataLoader(EntityManager, TransactionType) ' + + 'constructor to specify that JTA transactions are being used. Note that the client code ' + + 'needs to take care of transaction management in this case.', e) } } @@ -110,38 +114,29 @@ class TestDataLoader { * definitions. The files are expected to be UTF-8 encoded. */ void loadTestData(Collection entityDefinitionFiles) { - withEntityPersisterAndDeleterListeningInTransaction { + EntityPersister persister = new EntityPersister(entityManager) + EntityBuilder entityBuilder = EntityBuilder.newBuilder() + .addEntityCreatedListener(this) + .addEntityCreatedListener(persister) + .addEntityCreatedListener(entityDeleter) + + withTransaction { entityDefinitionFiles.each { - entityBuilder.buildEntities(FileReader.create(it)) + entityBuilder.build(FileReader.create(it)) } } } - private withEntityPersisterAndDeleterListeningInTransaction(Closure closure) { - EntityPersister persister = new EntityPersister(entityManager) - entityBuilder.addEntityCreatedListener(persister) - entityBuilder.addEntityCreatedListener(entityDeleter) - withTransaction { - closure() + @Override + public T getEntityByName(String name, Class entityClass) { + def entity = loadedEntities[name] + + if (entityClass != entity.class) { + throw new IllegalArgumentException( + "The class of the requested entity named '$name' does not match the requested class. Requested: $entityClass, Actual: ${entity.class}") } - entityBuilder.removeEntityCreatedListener(persister) - entityBuilder.removeEntityCreatedListener(entityDeleter) - } - /** - * Gets the entity with the specified name from the set of entities created from entity definition files passed to - * this {@code TestDataLoader}'s {@code loadTestData} method. - * - * If no entity with the specified name has been loaded, an {@link NoSuchElementException} is thrown. If an entity - * is found but has a different class than the passed {@code entityClass}, an {@link IllegalArgumentException} is - * thrown. - * - * @param name {@link String} - the requested entity's name - * @param entityClass the requested entity's {@link Class} - * @return the requested entity - */ - public T getEntityByName(String name, Class entityClass) { - return entityBuilder.getEntityByName(name, entityClass) + return (T) entity; } /** @@ -149,10 +144,8 @@ class TestDataLoader { * method and deletes all data from the database. */ void clearEntityCacheAndDatabase() { - withTransaction { - entityDeleter.deleteAllEntities() - clearEntityCache() - } + withTransaction { entityDeleter.deleteAllEntities() } + clearEntityCache() } /** @@ -160,7 +153,7 @@ class TestDataLoader { * method. */ void clearEntityCache() { - entityBuilder.clear(); + loadedEntities.clear(); } private void withTransaction(Closure doWithinTransaction) { @@ -188,4 +181,13 @@ class TestDataLoader { } } + @Override + public void onEntityCreated(String name, Object entity) { + loadedEntities[name]=entity + } + + @Override + public void clear() { + loadedEntities.clear() + } } diff --git a/src/main/java/de/triology/blog/testdataloader/EntityStore.java b/src/main/java/de/triology/blog/testdataloader/EntityStore.java new file mode 100755 index 0000000..c8c36ed --- /dev/null +++ b/src/main/java/de/triology/blog/testdataloader/EntityStore.java @@ -0,0 +1,55 @@ +/** + * MIT License + * + * Copyright (c) 2016 TRIOLOGY GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package de.triology.blog.testdataloader; + +import java.util.NoSuchElementException; + +/** + * An entity store which maintains the set of loaded entities. + * + */ +interface EntityStore { + + /** + * Gets the entity with the specified name from the set of entities created. + * + * If this {@code EntityBuilder} has not created an entity by the passed name a + * {@link NoSuchElementException} is thrown. If an entity is found but has a different type than + * the passed {@code entityClass}, an {@link IllegalArgumentException} is thrown. + * + * @param name + * {@link String} - the requested entity's name + * @param entityClass + * the requested entity's {@link Class} + * @return the requested entity + */ + T getEntityByName(String name, Class entityClass); + + /** + * Removes all entities from the store, so that they are no longer available through the + * {@code getEntityByName} method. + */ + void clear(); +} diff --git a/src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java b/src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java index fb62ab3..5ec9d16 100644 --- a/src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java +++ b/src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java @@ -23,55 +23,60 @@ */ package de.triology.blog.testdataloader; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.List; +import java.util.NoSuchElementException; + +import org.apache.commons.lang3.time.DateUtils; +import org.junit.Before; +import org.junit.Test; + import de.triology.blog.testdataloader.testentities.AnotherTestEntity; import de.triology.blog.testdataloader.testentities.BasicTestEntity; import de.triology.blog.testdataloader.testentities.InheritingEntity; import de.triology.blog.testdataloader.testentities.TestEntityWithToManyRelationship; import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelationship; -import org.apache.commons.lang3.time.DateUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.FileNotFoundException; -import java.util.*; - -import static org.junit.Assert.*; public class EntityBuilderTest { private EntityBuilder builder; + private EntityStore entityStore; @Before public void setUp() throws Exception { - builder = EntityBuilder.instance(); - builder.clear(); + builder = EntityBuilder.newBuilder(); callBuildEntitiesWithFile("tests/testEntityDefinitions.groovy"); } - private void callBuildEntitiesWithFile(String file) throws FileNotFoundException { - builder.buildEntities(FileReader.create(file)); - } - - @After - public void tearDown() throws Exception { - builder.clear(); + private void callBuildEntitiesWithFile(final String file) throws FileNotFoundException { + entityStore = builder.build(FileReader.create(file)); } @Test public void getsCreatedEntityByName() throws Exception { - BasicTestEntity entity = builder.getEntityByName("basicEntity", BasicTestEntity.class); + final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); assertNotNull(entity); } @Test(expected = NoSuchElementException.class) public void getEntityByNameFailsForNonexistingEntity() throws Exception { - builder.getEntityByName("notExisting", BasicTestEntity.class); + entityStore.getEntityByName("notExisting", BasicTestEntity.class); } @Test(expected = IllegalArgumentException.class) public void getEntityByNameFailsIfPassesClassDoesNotMatch() throws Exception { - builder.getEntityByName("basicEntity", AnotherTestEntity.class); + entityStore.getEntityByName("basicEntity", AnotherTestEntity.class); } @Test @@ -80,40 +85,39 @@ public void createsEntityFromDsl() throws Exception { } @Test - public void createsEntityThatUsesFieldFromMappedSuperclass() throws Exception { + public void createsEntityThatUsesFieldFromMappedSuperclass() throws Exception { callBuildEntitiesWithFile("tests/mappedSuperclass.groovy"); assertEntityOfClassWasBuilt("inherited", InheritingEntity.class); } - @Test public void createsMultipleEntitiesFromDsl() throws Exception { assertEntityOfClassWasBuilt("secondBasicEntity", BasicTestEntity.class); assertEntityOfClassWasBuilt("entityOfAnotherClass", AnotherTestEntity.class); } - private void assertEntityOfClassWasBuilt(String entityName, Class clazz) { - T entity = builder.getEntityByName(entityName, clazz); + private void assertEntityOfClassWasBuilt(final String entityName, final Class clazz) { + final T entity = entityStore.getEntityByName(entityName, clazz); assertNotNull("entity of name " + entityName + " was not built", entity); assertEquals(clazz, entity.getClass()); } @Test public void setsStringProperty() throws Exception { - BasicTestEntity entity = builder.getEntityByName("basicEntity", BasicTestEntity.class); + final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); assertEquals("a string value", entity.getStringProperty()); } @Test public void setsIntegerProperty() throws Exception { - BasicTestEntity entity = builder.getEntityByName("basicEntity", BasicTestEntity.class); + final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); assertEquals(5, (int) entity.getIntegerProperty()); } @Test public void setProgrammaticallyCreatedDateProperty() throws Exception { - BasicTestEntity entity = builder.getEntityByName("basicEntity", BasicTestEntity.class); - Calendar calendar = Calendar.getInstance(); + final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); + final Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.DAY_OF_MONTH, 18); calendar.set(Calendar.MONTH, Calendar.NOVEMBER); calendar.set(Calendar.YEAR, 2015); @@ -122,40 +126,40 @@ public void setProgrammaticallyCreatedDateProperty() throws Exception { @Test public void buildsReferencedEntityInPlace() throws Exception { - TestEntityWithToOneRelationship entity = builder.getEntityByName("entityWithToOneRelationship", + final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("entityWithToOneRelationship", TestEntityWithToOneRelationship.class); assertEntityOfClassWasBuilt("referencedInstance", BasicTestEntity.class); - BasicTestEntity referencedEntity = builder.getEntityByName("referencedInstance", BasicTestEntity.class); + final BasicTestEntity referencedEntity = entityStore.getEntityByName("referencedInstance", BasicTestEntity.class); assertSame(referencedEntity, entity.getReferencedEntity()); } @Test public void setsPropertiesOfEntitiesBuiltInPlace() throws Exception { - TestEntityWithToOneRelationship entity = builder.getEntityByName("entityWithToOneRelationship", + final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("entityWithToOneRelationship", TestEntityWithToOneRelationship.class); - BasicTestEntity referencedEntity = entity.getReferencedEntity(); + final BasicTestEntity referencedEntity = entity.getReferencedEntity(); assertEquals("string in referenced entity", referencedEntity.getStringProperty()); assertEquals(222, (int) referencedEntity.getIntegerProperty()); } @Test public void buildEntitiesWithArbitraryNesting() throws Exception { - TestEntityWithToOneRelationship entity = builder.getEntityByName("deeplyNestedEntities", + final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("deeplyNestedEntities", TestEntityWithToOneRelationship.class); - assertSame(builder.getEntityByName("nest1", TestEntityWithToOneRelationship.class), + assertSame(entityStore.getEntityByName("nest1", TestEntityWithToOneRelationship.class), entity.getTestEntityWithToOneRelationship()); - assertSame(builder.getEntityByName("nest2", TestEntityWithToOneRelationship.class), + assertSame(entityStore.getEntityByName("nest2", TestEntityWithToOneRelationship.class), entity.getTestEntityWithToOneRelationship().getTestEntityWithToOneRelationship()); - assertSame(builder.getEntityByName("nest3", BasicTestEntity.class), + assertSame(entityStore.getEntityByName("nest3", BasicTestEntity.class), entity.getTestEntityWithToOneRelationship().getTestEntityWithToOneRelationship().getReferencedEntity()); - assertEquals("deeply nested string", builder.getEntityByName("nest3", BasicTestEntity.class).getStringProperty()); + assertEquals("deeply nested string", entityStore.getEntityByName("nest3", BasicTestEntity.class).getStringProperty()); } @Test public void resolvesReferences() throws Exception { - TestEntityWithToOneRelationship entity = builder.getEntityByName("entityReferencingPreviouslyCreatedEntity", + final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("entityReferencingPreviouslyCreatedEntity", TestEntityWithToOneRelationship.class); - assertSame(builder.getEntityByName("secondBasicEntity", BasicTestEntity.class), entity.getReferencedEntity()); + assertSame(entityStore.getEntityByName("secondBasicEntity", BasicTestEntity.class), entity.getReferencedEntity()); } @Test(expected = EntityBuildingException.class) @@ -163,7 +167,6 @@ public void failsIfReferencedEntityDoesNotExist() throws Exception { callBuildEntitiesWithFile("tests/failingBecauseOfMissingReferencedEntity.groovy"); } - @Test(expected = EntityBuildingException.class) public void failsIfAnEntityNameHasAlreadyBeenUsed() throws Exception { callBuildEntitiesWithFile("tests/failingBecauseOfReusedName.groovy"); @@ -171,13 +174,13 @@ public void failsIfAnEntityNameHasAlreadyBeenUsed() throws Exception { @Test public void setsCollectionOfReferencedEntities() throws Exception { - TestEntityWithToManyRelationship entity = builder.getEntityByName("entityWithCollection", + final TestEntityWithToManyRelationship entity = entityStore.getEntityByName("entityWithCollection", TestEntityWithToManyRelationship.class); - Collection toManyRelationship = entity.getToManyRelationship(); + final Collection toManyRelationship = entity.getToManyRelationship(); assertEquals(2, toManyRelationship.size()); BasicTestEntity referencedEntity1 = null; BasicTestEntity referencedEntity2 = null; - for (BasicTestEntity basicTestEntity : toManyRelationship) { + for (final BasicTestEntity basicTestEntity : toManyRelationship) { if (referencedEntity1 == null) { referencedEntity1 = basicTestEntity; } else { @@ -193,10 +196,9 @@ public void setsCollectionOfReferencedEntities() throws Exception { @Test public void notifiesEntityCreatedListenerInTheOrderOfEntityCreation() throws Exception { - builder.clear(); final List entitiesInOrderOfCreation = new ArrayList(); builder.addEntityCreatedListener(new EntityCreatedListener() { - public void entityCreated(Object entity) { + public void onEntityCreated(final String name, final Object entity) { entitiesInOrderOfCreation.add(entity); } }); @@ -208,16 +210,32 @@ public void entityCreated(Object entity) { assertEquals(TestEntityWithToOneRelationship.class, entitiesInOrderOfCreation.get(3).getClass()); } - @Test (expected = NoSuchElementException.class) + @Test(expected = NoSuchElementException.class) public void clearsEntities() throws Exception { try { - builder.getEntityByName("basicEntity", BasicTestEntity.class); - } catch (NoSuchElementException e) { + entityStore.getEntityByName("basicEntity", BasicTestEntity.class); + } catch (final NoSuchElementException e) { e.printStackTrace(); fail("basicEntity already was not available before calling clearEntityCacheAndDatabase"); } - builder.clear(); - builder.getEntityByName("basicEntity", BasicTestEntity.class); + entityStore.clear(); + entityStore.getEntityByName("basicEntity", BasicTestEntity.class); + } + + @Test + public void builderCreatesNewStoreForEachBuildAttempt() throws FileNotFoundException { + final EntityStore oldStore = EntityBuilder.newBuilder().build(FileReader.create("tests/testEntityDefinitions.groovy")); + final EntityStore newStore = EntityBuilder.newBuilder().build(FileReader.create("tests/testEntityDefinitions.groovy")); + + assertNotEquals(oldStore, newStore); + + final BasicTestEntity oldEntity = oldStore.getEntityByName("basicEntity", BasicTestEntity.class); + assertNotNull(oldEntity); + + final BasicTestEntity newEntity = newStore.getEntityByName("basicEntity", BasicTestEntity.class); + assertNotNull(newEntity); + + assertNotEquals(oldEntity, newEntity); } } \ No newline at end of file diff --git a/src/test/java/de/triology/blog/testdataloader/EntityDeleterTest.java b/src/test/java/de/triology/blog/testdataloader/EntityDeleterTest.java index f39cf15..3e08156 100644 --- a/src/test/java/de/triology/blog/testdataloader/EntityDeleterTest.java +++ b/src/test/java/de/triology/blog/testdataloader/EntityDeleterTest.java @@ -23,15 +23,6 @@ */ package de.triology.blog.testdataloader; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -import javax.persistence.EntityManager; - import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.Matchers.any; import static org.mockito.Mockito.inOrder; @@ -40,6 +31,15 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import javax.persistence.EntityManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + @RunWith(MockitoJUnitRunner.class) public class EntityDeleterTest { @@ -55,17 +55,17 @@ public void setUp() throws Exception { @Test public void deletesAllCreatedEntitiesInReversedOrder() throws Exception { - Object entity1 = new Object(); - Object entity2 = new Object(); - Object entity3 = new Object(); + final Object entity1 = new Object(); + final Object entity2 = new Object(); + final Object entity3 = new Object(); - entityDeleter.entityCreated(entity1); - entityDeleter.entityCreated(entity2); - entityDeleter.entityCreated(entity3); + entityDeleter.onEntityCreated("entity1", entity1); + entityDeleter.onEntityCreated("entity2", entity2); + entityDeleter.onEntityCreated("entity3", entity3); entityDeleter.deleteAllEntities(); - InOrder inOrder = inOrder(entityManager); + final InOrder inOrder = inOrder(entityManager); inOrder.verify(entityManager).remove(entity3); inOrder.verify(entityManager).remove(entity2); inOrder.verify(entityManager).remove(entity1); @@ -73,9 +73,9 @@ public void deletesAllCreatedEntitiesInReversedOrder() throws Exception { @Test public void deletesAnEntityOnlyOnce() throws Exception { - EntityDeleter entityDeleter = new EntityDeleter(entityManager); - Object entity = new Object(); - entityDeleter.entityCreated(entity); + final EntityDeleter entityDeleter = new EntityDeleter(entityManager); + final Object entity = new Object(); + entityDeleter.onEntityCreated("entity", entity); entityDeleter.deleteAllEntities(); entityDeleter.deleteAllEntities(); @@ -85,34 +85,34 @@ public void deletesAnEntityOnlyOnce() throws Exception { @Test public void mergesDetachedEntitiesBeforeRemovingThem() throws Exception { - Object entity = new Object(); - entityDeleter.entityCreated(entity); + final Object entity = new Object(); + entityDeleter.onEntityCreated("entity", entity); when(entityManager.contains(entity)).thenReturn(false); entityDeleter.deleteAllEntities(); - InOrder inOrder = inOrder(entityManager); + final InOrder inOrder = inOrder(entityManager); inOrder.verify(entityManager).merge(entity); inOrder.verify(entityManager).remove(entity); } @Test public void doesNotMergeAttachedEntitiesBeforeRemovingThem() throws Exception { - Object entity = new Object(); - entityDeleter.entityCreated(entity); + final Object entity = new Object(); + entityDeleter.onEntityCreated("entity", entity); when(entityManager.contains(entity)).thenReturn(true); entityDeleter.deleteAllEntities(); - InOrder inOrder = inOrder(entityManager); + final InOrder inOrder = inOrder(entityManager); inOrder.verify(entityManager, never()).merge(entity); inOrder.verify(entityManager).remove(entity); } @Test public void doesNotDeleteAlreadyRemovedEntities() throws Exception { - Object entity = new Object(); - entityDeleter.entityCreated(entity); + final Object entity = new Object(); + entityDeleter.onEntityCreated("entity", entity); when(entityManager.merge(entity)).thenThrow(IllegalArgumentException.class); entityDeleter.deleteAllEntities(); diff --git a/src/test/java/de/triology/blog/testdataloader/EntityPersisterTest.java b/src/test/java/de/triology/blog/testdataloader/EntityPersisterTest.java index 90ec23b..b5e049f 100644 --- a/src/test/java/de/triology/blog/testdataloader/EntityPersisterTest.java +++ b/src/test/java/de/triology/blog/testdataloader/EntityPersisterTest.java @@ -23,21 +23,21 @@ */ package de.triology.blog.testdataloader; -import org.junit.Test; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import javax.persistence.EntityManager; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; +import org.junit.Test; public class EntityPersisterTest { @Test public void persistsCreatedEntities() throws Exception { - EntityManager entityManagerMock = mock(EntityManager.class); - EntityPersister entityPersister = new EntityPersister(entityManagerMock); - Object entity = new Object(); - entityPersister.entityCreated(entity); + final EntityManager entityManagerMock = mock(EntityManager.class); + final EntityPersister entityPersister = new EntityPersister(entityManagerMock); + final Object entity = new Object(); + entityPersister.onEntityCreated("entity", entity); verify(entityManagerMock).persist(entity); } } \ No newline at end of file diff --git a/src/test/resources/demo/testData.groovy b/src/test/resources/demo/testData.groovy index 593fbf9..9124135 100644 --- a/src/test/resources/demo/testData.groovy +++ b/src/test/resources/demo/testData.groovy @@ -23,7 +23,6 @@ */ import de.triology.blog.testdataloader.demo.Department -import static de.triology.blog.testdataloader.EntityBuilder.create import de.triology.blog.testdataloader.demo.User create User, 'Peter', { diff --git a/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy b/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy index e1e02cd..4e9d0de 100644 --- a/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy +++ b/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy @@ -23,8 +23,6 @@ */ import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelationship -import static de.triology.blog.testdataloader.EntityBuilder.create - create TestEntityWithToOneRelationship, 'entityReferencingANonexistingEntity', { referencedEntity = notExistingReference } \ No newline at end of file diff --git a/src/test/resources/tests/failingBecauseOfReusedName.groovy b/src/test/resources/tests/failingBecauseOfReusedName.groovy index b2ef767..1800796 100644 --- a/src/test/resources/tests/failingBecauseOfReusedName.groovy +++ b/src/test/resources/tests/failingBecauseOfReusedName.groovy @@ -24,7 +24,5 @@ import de.triology.blog.testdataloader.testentities.AnotherTestEntity import de.triology.blog.testdataloader.testentities.BasicTestEntity -import static de.triology.blog.testdataloader.EntityBuilder.create - create BasicTestEntity, 'nameThatIsUsedTwoTimes', {} create AnotherTestEntity, 'nameThatIsUsedTwoTimes', {} diff --git a/src/test/resources/tests/mappedSuperclass.groovy b/src/test/resources/tests/mappedSuperclass.groovy index b891b71..9203627 100644 --- a/src/test/resources/tests/mappedSuperclass.groovy +++ b/src/test/resources/tests/mappedSuperclass.groovy @@ -26,8 +26,6 @@ import de.triology.blog.testdataloader.testentities.InheritingEntity * SOFTWARE. */ -import static de.triology.blog.testdataloader.EntityBuilder.create - create(InheritingEntity, "inherited") { inheritedField = "this Field is privately defined in the superclass" nonInheritedField = "this Field is privately defined in the the actual class" diff --git a/src/test/resources/tests/testEntityDefinitions.groovy b/src/test/resources/tests/testEntityDefinitions.groovy index d43784a..cb6a989 100644 --- a/src/test/resources/tests/testEntityDefinitions.groovy +++ b/src/test/resources/tests/testEntityDefinitions.groovy @@ -28,8 +28,6 @@ import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelations import java.text.SimpleDateFormat -import static de.triology.blog.testdataloader.EntityBuilder.create - create BasicTestEntity, 'basicEntity', { stringProperty = 'a string value' integerProperty = 5 diff --git a/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy b/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy index 883d27d..b68d723 100644 --- a/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy +++ b/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy @@ -25,8 +25,6 @@ import de.triology.blog.testdataloader.testentities.AnotherTestEntity import de.triology.blog.testdataloader.testentities.BasicTestEntity import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelationship -import static de.triology.blog.testdataloader.EntityBuilder.create - create TestEntityWithToOneRelationship, 'entityWithToOneRelationship', { referencedEntity = create BasicTestEntity, 'referencedInstance', { stringProperty = 'string in referenced entity' From 682b80102f536134b1782f8793aee8bca1d410c7 Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Wed, 15 Nov 2017 09:41:11 +0100 Subject: [PATCH 3/8] Splitted the project into two parts: one responsible for the building (handling of the defined DSL) and one responsible for the managing of the built objects in an EntityManager. New tests for the builder part implemented. --- pom.xml | 471 +++++++++--------- .../builder}/EntityBuilder.groovy | 29 +- .../builder}/EntityBuilderDsl.groovy | 56 +-- .../builder/EntityBuilderException.groovy} | 9 +- .../builder/EntityBuilderListener.groovy} | 4 +- .../builder}/EntityBuilderScript.groovy | 2 +- .../loader}/EntityDeleter.groovy | 5 +- .../loader}/EntityPersister.groovy | 6 +- .../loader}/TestDataLoader.groovy | 31 +- .../util}/FileReader.groovy | 2 +- .../blog/testdataloader/EntityStore.java | 55 -- .../builder/EntityBuilderDslTest.groovy | 105 ++++ .../testdata/builder/EntityBuilderTest.groovy | 96 ++++ .../blog/testdata/util}/FileReaderTest.java | 4 +- .../loader}/EntityDeleterTest.java | 4 +- .../loader}/EntityPersisterTest.java | 4 +- .../loader}/TestDataLoaderTest.java | 8 +- .../loader/it}/Department.java | 2 +- .../loader/it/TestDataLoaderIT.java} | 7 +- .../demo => testdata/loader/it}/User.java | 2 +- .../testentities/AnotherTestEntity.java | 2 +- .../loader}/testentities/BaseClass.java | 2 +- .../loader}/testentities/BasicTestEntity.java | 2 +- .../testentities/InheritingEntity.java | 2 +- .../TestEntityWithToManyRelationship.java | 2 +- .../TestEntityWithToOneRelationship.java | 2 +- .../testdataloader/EntityBuilderTest.java | 241 --------- src/test/resources/META-INF/persistence.xml | 26 - src/test/resources/demo/testData.groovy | 28 +- ...ingBecauseOfMissingReferencedEntity.groovy | 25 +- .../tests/failingBecauseOfReusedName.groovy | 25 +- .../resources/tests/mappedSuperclass.groovy | 28 +- .../tests/testEntityDefinitions.groovy | 31 +- ...fEntityCreatedListenerNotifications.groovy | 29 +- 34 files changed, 535 insertions(+), 812 deletions(-) rename src/main/groovy/de/triology/blog/{testdataloader => testdata/builder}/EntityBuilder.groovy (73%) rename src/main/groovy/de/triology/blog/{testdataloader => testdata/builder}/EntityBuilderDsl.groovy (62%) rename src/main/groovy/de/triology/blog/{testdataloader/EntityBuildingException.groovy => testdata/builder/EntityBuilderException.groovy} (82%) rename src/main/groovy/de/triology/blog/{testdataloader/EntityCreatedListener.groovy => testdata/builder/EntityBuilderListener.groovy} (95%) rename src/main/groovy/de/triology/blog/{testdataloader => testdata/builder}/EntityBuilderScript.groovy (96%) rename src/main/groovy/de/triology/blog/{testdataloader => testdata/loader}/EntityDeleter.groovy (94%) rename src/main/groovy/de/triology/blog/{testdataloader => testdata/loader}/EntityPersister.groovy (90%) rename src/main/groovy/de/triology/blog/{testdataloader => testdata/loader}/TestDataLoader.groovy (87%) rename src/main/groovy/de/triology/blog/{testdataloader => testdata/util}/FileReader.groovy (98%) delete mode 100755 src/main/java/de/triology/blog/testdataloader/EntityStore.java create mode 100755 src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderDslTest.groovy create mode 100755 src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy rename src/test/java/de/{triology/blog/testdataloader => trilogy/blog/testdata/util}/FileReaderTest.java (95%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/EntityDeleterTest.java (97%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/EntityPersisterTest.java (94%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/TestDataLoaderTest.java (95%) rename src/test/java/de/triology/blog/{testdataloader/demo => testdata/loader/it}/Department.java (97%) rename src/test/java/de/triology/blog/{testdataloader/demo/Demo.java => testdata/loader/it/TestDataLoaderIT.java} (96%) rename src/test/java/de/triology/blog/{testdataloader/demo => testdata/loader/it}/User.java (98%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/testentities/AnotherTestEntity.java (95%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/testentities/BaseClass.java (96%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/testentities/BasicTestEntity.java (97%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/testentities/InheritingEntity.java (95%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/testentities/TestEntityWithToManyRelationship.java (96%) rename src/test/java/de/triology/blog/{testdataloader => testdata/loader}/testentities/TestEntityWithToOneRelationship.java (97%) delete mode 100644 src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java diff --git a/pom.xml b/pom.xml index caf956b..6504ef5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,262 +1,257 @@ - - - - 4.0.0 + + ch.qos.logback + logback-classic + 1.1.7 + - com.github.triologygmbh - test-data-loader - 0.2.2-SNAPSHOT + + org.eclipse.persistence + javax.persistence + 2.1.1 + provided + - - UTF-8 - src/main/groovy - src/test/groovy - target/jacoco.exec - + + org.eclipse.persistence + eclipselink + 2.6.3 + test + + + junit + junit + 4.12 + test + + + com.h2database + h2 + 1.4.192 + test + + + org.apache.commons + commons-lang3 + 3.4 + test + + + org.mockito + mockito-all + 1.10.19 + test + + + org.spockframework + spock-core + 1.1-groovy-2.4 + test + + + net.bytebuddy + byte-buddy + 1.7.9 + test + + - - scm:git:git@github.com:triologygmbh/test-data-loader.git - scm:git:git@github.com:triologygmbh/test-data-loader.git - https://github.com/triologygmbh/test-data-loader - HEAD - + + - - - org.codehaus.groovy - groovy-all - 2.4.7 - - - - org.slf4j - slf4j-api - 1.7.21 - - - - ch.qos.logback - logback-classic - 1.1.7 - + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + de.triology.blog.testdataloader.demo.Demo + + + - - org.eclipse.persistence - javax.persistence - 2.1.1 - provided - + + org.codehaus.mojo + build-helper-maven-plugin + 1.12 + + + add-resource + generate-resources + + add-resource + + + + + src/main/groovy + + + src/test/groovy + + + + + + - - org.eclipse.persistence - eclipselink - 2.6.3 - test - - - junit - junit - 4.12 - test - - - com.h2database - h2 - 1.4.192 - test - - - org.apache.commons - commons-lang3 - 3.4 - test - - - org.mockito - mockito-all - 1.10.19 - test - - + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + true + + groovy-eclipse-compiler + + + + org.codehaus.groovy + groovy-eclipse-compiler + 2.9.2-01 + + + org.codehaus.groovy + groovy-eclipse-batch + 2.4.3-01 + + + - - + + + com.mycila + license-maven-plugin + 2.11 + +
LICENSE
+ + **/README* + **/LICENSE + **/Jenkinsfile + **/pom.xml + src/test/resources/** + src/main/resources/** + +
- - org.apache.maven.plugins - maven-surefire-plugin - 2.19.1 - - - de.triology.blog.testdataloader.demo.Demo - - - + + + + check + + + +
- - org.codehaus.mojo - build-helper-maven-plugin - 1.12 - - - add-resource - generate-resources - - add-resource - - - - - src/main/groovy - - - src/test/groovy - - - - - - + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + + jar + + + + - - org.apache.maven.plugins - maven-compiler-plugin - 3.5.1 - true - - groovy-eclipse-compiler - - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.2-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.4.3-01 - - - + + com.bluetrainsoftware.maven + groovydoc-maven-plugin + 1.3 + + + attach-docs + package + + attach-docs + + + + - - - com.mycila - license-maven-plugin - 2.11 - -
LICENSE
-
+ + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + + + maven-deploy-plugin + 2.8.2 + + internal.repo::default::file://${project.build.directory}/release + + +
+
- - - - check - - - - + + + + jenkins - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - attach-sources - - jar - - - - + + + env.BUILD_URL + + - - com.bluetrainsoftware.maven - groovydoc-maven-plugin - 1.3 - - - attach-docs - package - - attach-docs - - - - + + - - org.apache.maven.plugins - maven-release-plugin - 2.5.3 - - - - maven-deploy-plugin - 2.8.2 - - internal.repo::default::file://${project.build.directory}/release - - + + + org.jacoco + jacoco-maven-plugin + + + initialize + + prepare-agent + + + + - - - - - - jenkins - - - - env.BUILD_URL - - - - - - - - - org.jacoco - jacoco-maven-plugin - - - initialize - - prepare-agent - - - - - - - - +
+ +
diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilder.groovy b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilder.groovy similarity index 73% rename from src/main/groovy/de/triology/blog/testdataloader/EntityBuilder.groovy rename to src/main/groovy/de/triology/blog/testdata/builder/EntityBuilder.groovy index e459220..e3585b5 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilder.groovy +++ b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilder.groovy @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.builder import org.codehaus.groovy.control.CompilerConfiguration @@ -30,47 +30,36 @@ import org.codehaus.groovy.control.CompilerConfiguration */ class EntityBuilder { - private List entityCreatedListeners = [] - - private EntityBuilder() {} - - public static EntityBuilder newBuilder() { - return new EntityBuilder() - } - - + private List listeners = [] /** * Builds the entities defined in the provided by the passed Reader. * - * @param entityDefinitionReader Reader - a Reader for the file containing the entity definitions + * @param reader - a Reader for the file containing the entity definitions */ - public EntityStore build(Reader entityDefinitionReader) { + public void build(Reader reader) { CompilerConfiguration compilerConfiguration = new CompilerConfiguration() compilerConfiguration.scriptBaseClass = EntityBuilderScript.class.name - EntityBuilderDsl dsl = new EntityBuilderDsl(this) Binding binding = new Binding() - binding.dsl = dsl + binding.dsl = new EntityBuilderDsl(this) GroovyShell shell = new GroovyShell(this.class.classLoader, binding, compilerConfiguration) - Script script = shell.parse(entityDefinitionReader) + Script script = shell.parse(reader) script.run() - - return dsl } /** * Adds an {@link EntityCreatedListener} that gets notified every time an entity is completely created. * @param listener {@link EntityCreatedListener} */ - public EntityBuilder addEntityCreatedListener(EntityCreatedListener listener) { - entityCreatedListeners += listener + public EntityBuilder addEntityBuilderListener(EntityBuilderListener listener) { + listeners += listener return this } protected void fireEntityCreated(String entityName, Object entity) { - entityCreatedListeners.each { it.onEntityCreated(entityName, entity) } + listeners*.onEntityCreated(entityName, entity) } } diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderDsl.groovy b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderDsl.groovy similarity index 62% rename from src/main/groovy/de/triology/blog/testdataloader/EntityBuilderDsl.groovy rename to src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderDsl.groovy index 3317e56..dbff3fd 100755 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderDsl.groovy +++ b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderDsl.groovy @@ -22,15 +22,15 @@ * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.builder -class EntityBuilderDsl implements EntityStore { +class EntityBuilderDsl { private Map entitiesByName = [:] - private EntityBuilder builder; + private EntityBuilder builder protected EntityBuilderDsl(EntityBuilder builder) { - this.builder = builder; + this.builder = builder } /** @@ -44,32 +44,29 @@ class EntityBuilderDsl implements EntityStore { */ public T create(@DelegatesTo.Target Class entityClass, String entityName, @DelegatesTo(strategy = Closure.DELEGATE_FIRST, genericTypeIndex = 0) Closure entityData = {}) { + T entity = createEntityInstance(entityName, entityClass) - executeEntityDataDefinition(entityData, entity) + + def rehydrated = entityData.rehydrate(entity, this, this) + rehydrated.call() + builder.fireEntityCreated(entityName, entity) return entity } private T createEntityInstance(String entityName, Class entityClass) { - ensureNameHasNotYetBeenAssigned(entityName, entityClass) - T entity = entityClass.newInstance() - entitiesByName[entityName] = entity; - return entity - } - - private void ensureNameHasNotYetBeenAssigned(String entityName, Class requestedEntityClass) { if (entitiesByName[entityName]) { - throw new EntityBuildingException( - "attempt to create an instance of $requestedEntityClass under the name of '$entityName' but an " + + throw new EntityBuilderException( + "attempt to create an instance of $entityClass under the name of '$entityName' but an " + "entity with that name already exists: ${entitiesByName[entityName]}") } - } - private void executeEntityDataDefinition(Closure entityDataDefinition, Object entity) { - entityDataDefinition = entityDataDefinition.rehydrate(entity, this, this) - entityDataDefinition.call() + T entity = entityClass.newInstance() + entitiesByName[entityName] = entity + return entity } + /** * Implementation of Groovy's {@code propertyMissing} that returns the entity previously created under the property * name. This Method will be called during entity creation, when an entity is referenced. @@ -81,27 +78,6 @@ class EntityBuilderDsl implements EntityStore { if (entitiesByName[name]) { return entitiesByName[name] } - throw new EntityBuildingException("requested reference for entity with name '$name' cannot be resolved") - } - - - @Override - public T getEntityByName(String name, Class entityClass) { - def entity = entitiesByName[name] - if (!entity) { - throw new NoSuchElementException("an entity named '$name' has not been created by the EntityBuilder") - } - - if (entityClass != entity.class) { - throw new IllegalArgumentException( - "The class of the requested entity named '$name' does not match the requested class. Requested: $entityClass, Actual: ${entity.class}") - } - - return (T) entity; - } - - @Override - public void clear() { - entitiesByName.clear() + throw new EntityBuilderException("requested reference for entity with name '$name' cannot be resolved") } } diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityBuildingException.groovy b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderException.groovy similarity index 82% rename from src/main/groovy/de/triology/blog/testdataloader/EntityBuildingException.groovy rename to src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderException.groovy index 74653d7..eda63d1 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityBuildingException.groovy +++ b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderException.groovy @@ -21,15 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.builder /** - * A {@link RuntimeException} that can be used while building entities + * A {@link RuntimeException} that is used in case of errors encountered while building the entities */ -class EntityBuildingException extends RuntimeException { +class EntityBuilderException extends RuntimeException { - EntityBuildingException(String message) { + EntityBuilderException(String message) { super(message) } - } diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityCreatedListener.groovy b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderListener.groovy similarity index 95% rename from src/main/groovy/de/triology/blog/testdataloader/EntityCreatedListener.groovy rename to src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderListener.groovy index 6bcbfc9..d01a162 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityCreatedListener.groovy +++ b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderListener.groovy @@ -21,12 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.builder /** * Listener for entity creation. Gets notified every time an entity is completely created. */ -interface EntityCreatedListener { +interface EntityBuilderListener { /** * Is called every time an entity is completely created, including all referenced entities. diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderScript.groovy b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderScript.groovy similarity index 96% rename from src/main/groovy/de/triology/blog/testdataloader/EntityBuilderScript.groovy rename to src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderScript.groovy index 347ca48..6deba5e 100755 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityBuilderScript.groovy +++ b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderScript.groovy @@ -22,7 +22,7 @@ * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.builder abstract class EntityBuilderScript extends Script { diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityDeleter.groovy b/src/main/groovy/de/triology/blog/testdata/loader/EntityDeleter.groovy similarity index 94% rename from src/main/groovy/de/triology/blog/testdataloader/EntityDeleter.groovy rename to src/main/groovy/de/triology/blog/testdata/loader/EntityDeleter.groovy index 50f8aae..4223ad1 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityDeleter.groovy +++ b/src/main/groovy/de/triology/blog/testdata/loader/EntityDeleter.groovy @@ -21,13 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.loader import javax.persistence.EntityManager import org.slf4j.Logger import org.slf4j.LoggerFactory +import de.triology.blog.testdata.builder.EntityBuilderListener import groovy.transform.PackageScope /** @@ -35,7 +36,7 @@ import groovy.transform.PackageScope * for later deletion. */ @PackageScope -class EntityDeleter implements EntityCreatedListener { +class EntityDeleter implements EntityBuilderListener { private static final Logger LOG = LoggerFactory.getLogger(EntityDeleter) diff --git a/src/main/groovy/de/triology/blog/testdataloader/EntityPersister.groovy b/src/main/groovy/de/triology/blog/testdata/loader/EntityPersister.groovy similarity index 90% rename from src/main/groovy/de/triology/blog/testdataloader/EntityPersister.groovy rename to src/main/groovy/de/triology/blog/testdata/loader/EntityPersister.groovy index 84ed379..ed2f7f8 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/EntityPersister.groovy +++ b/src/main/groovy/de/triology/blog/testdata/loader/EntityPersister.groovy @@ -21,14 +21,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.loader import javax.persistence.EntityManager +import de.triology.blog.testdata.builder.EntityBuilderListener + /** * An EntityCreatedListener that persists created entities. */ -class EntityPersister implements EntityCreatedListener { +class EntityPersister implements EntityBuilderListener { private EntityManager entityManager diff --git a/src/main/groovy/de/triology/blog/testdataloader/TestDataLoader.groovy b/src/main/groovy/de/triology/blog/testdata/loader/TestDataLoader.groovy similarity index 87% rename from src/main/groovy/de/triology/blog/testdataloader/TestDataLoader.groovy rename to src/main/groovy/de/triology/blog/testdata/loader/TestDataLoader.groovy index c2f2a74..2c81c10 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/TestDataLoader.groovy +++ b/src/main/groovy/de/triology/blog/testdata/loader/TestDataLoader.groovy @@ -21,18 +21,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.loader import javax.persistence.EntityManager import org.slf4j.Logger import org.slf4j.LoggerFactory +import de.triology.blog.testdata.builder.EntityBuilder +import de.triology.blog.testdata.builder.EntityBuilderListener +import de.triology.blog.testdata.util.FileReader + /** * Loads test data from entity definition files, saves them to a database via a specified {@link EntityManager} and * makes the entities available by their names as defined in the entity definition files. */ -class TestDataLoader implements EntityStore, EntityCreatedListener { +class TestDataLoader implements EntityBuilderListener { /** * Defines the transaction type that the {@link EntityManager} passed to the {@code TestDataLoader} is configured with. @@ -115,10 +119,10 @@ class TestDataLoader implements EntityStore, EntityCreatedListener { */ void loadTestData(Collection entityDefinitionFiles) { EntityPersister persister = new EntityPersister(entityManager) - EntityBuilder entityBuilder = EntityBuilder.newBuilder() - .addEntityCreatedListener(this) - .addEntityCreatedListener(persister) - .addEntityCreatedListener(entityDeleter) + EntityBuilder entityBuilder = new EntityBuilder() + .addEntityBuilderListener(this) + .addEntityBuilderListener(persister) + .addEntityBuilderListener(entityDeleter) withTransaction { entityDefinitionFiles.each { @@ -127,7 +131,19 @@ class TestDataLoader implements EntityStore, EntityCreatedListener { } } - @Override + /** + * Gets the entity with the specified name from the set of entities created. + * + * If this {@code EntityBuilder} has not created an entity by the passed name a + * {@link NoSuchElementException} is thrown. If an entity is found but has a different type than + * the passed {@code entityClass}, an {@link IllegalArgumentException} is thrown. + * + * @param name + * {@link String} - the requested entity's name + * @param entityClass + * the requested entity's {@link Class} + * @return the requested entity + */ public T getEntityByName(String name, Class entityClass) { def entity = loadedEntities[name] @@ -186,7 +202,6 @@ class TestDataLoader implements EntityStore, EntityCreatedListener { loadedEntities[name]=entity } - @Override public void clear() { loadedEntities.clear() } diff --git a/src/main/groovy/de/triology/blog/testdataloader/FileReader.groovy b/src/main/groovy/de/triology/blog/testdata/util/FileReader.groovy similarity index 98% rename from src/main/groovy/de/triology/blog/testdataloader/FileReader.groovy rename to src/main/groovy/de/triology/blog/testdata/util/FileReader.groovy index 9ed9fc7..df999ec 100644 --- a/src/main/groovy/de/triology/blog/testdataloader/FileReader.groovy +++ b/src/main/groovy/de/triology/blog/testdata/util/FileReader.groovy @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader +package de.triology.blog.testdata.util import org.slf4j.Logger import org.slf4j.LoggerFactory diff --git a/src/main/java/de/triology/blog/testdataloader/EntityStore.java b/src/main/java/de/triology/blog/testdataloader/EntityStore.java deleted file mode 100755 index c8c36ed..0000000 --- a/src/main/java/de/triology/blog/testdataloader/EntityStore.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package de.triology.blog.testdataloader; - -import java.util.NoSuchElementException; - -/** - * An entity store which maintains the set of loaded entities. - * - */ -interface EntityStore { - - /** - * Gets the entity with the specified name from the set of entities created. - * - * If this {@code EntityBuilder} has not created an entity by the passed name a - * {@link NoSuchElementException} is thrown. If an entity is found but has a different type than - * the passed {@code entityClass}, an {@link IllegalArgumentException} is thrown. - * - * @param name - * {@link String} - the requested entity's name - * @param entityClass - * the requested entity's {@link Class} - * @return the requested entity - */ - T getEntityByName(String name, Class entityClass); - - /** - * Removes all entities from the store, so that they are no longer available through the - * {@code getEntityByName} method. - */ - void clear(); -} diff --git a/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderDslTest.groovy b/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderDslTest.groovy new file mode 100755 index 0000000..913a487 --- /dev/null +++ b/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderDslTest.groovy @@ -0,0 +1,105 @@ +/** + * MIT License + * + * Copyright (c) 2016 TRIOLOGY GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package de.triology.blog.testdata.builder + +import spock.lang.Specification + +class EntityBuilderDslTest extends Specification { + + static class SimpleClass { + String prop; + } + + static class ComplexClass { + SimpleClass simple + String prop + ComplexClass complex + } + + EntityBuilder builder + EntityBuilderDsl dsl + + def setup() { + builder = Mock() + dsl = new EntityBuilderDsl(builder) + } + + def "should create single instance and set single property" () { + given: "dsl configuration from setup" + + when: "a simple entity class is created" + dsl.create(SimpleClass, "simple", { prop = "Value" }) + + then: "the builder receives an event with the specified name for the entity and the built entity" + 1 * builder.fireEntityCreated("simple", { it.prop == "Value" }) + } + + def "should create multiple instances and set given properties" () { + given: "dsl configuration from setup" + SimpleClass capturedSimple + + when: "two entites, a simple and a complex one are created" + dsl.create(ComplexClass, "complex", { + prop = "ComplexValue" + simple = create(SimpleClass, "simple", { prop = "SimpleValue" }) + complex = complex + }) + + then: "the builder receives exactly two events, both with the specified name for the entity and the built entity" + 1 * builder.fireEntityCreated("simple", { + it.prop == "SimpleValue" + capturedSimple = it + }) + 1 * builder.fireEntityCreated("complex", { + it.prop == "ComplexValue" + it.complex == it + it.simple == capturedSimple + }) + + 0 * builder._ + } + + def "should throw exception when the referenced entity is not available" () { + given: "dsl configuration from setup" + + when: "an attempt is made to create an entity by specifying another not existing entity" + dsl.create(ComplexClass, "complex", { simple = foo }) + + then: "an exception is thrown" + EntityBuilderException e = thrown() + e.message.contains("'foo' cannot be resolved") + } + + def "should throw exception when entity name is reused" () { + given: "dsl configuration from setup" + + when: "an attempt is made to create an entity using an already used name" + dsl.create(ComplexClass, "simple", { prop = "Value1" }) + dsl.create(ComplexClass, "simple", { prop = "Value2" }) + + then: "an exception is thrown" + EntityBuilderException e = thrown() + e.message.contains("entity with that name already exists") + } +} diff --git a/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy b/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy new file mode 100755 index 0000000..49c7532 --- /dev/null +++ b/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy @@ -0,0 +1,96 @@ +/** + * MIT License + * + * Copyright (c) 2016 TRIOLOGY GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package de.triology.blog.testdata.builder + +import spock.lang.Specification + +class EntityBuilderTest extends Specification { + + static class SimpleClass { + String prop; + } + + static class ComplexClass { + SimpleClass simple + String prop + ComplexClass complex + } + + EntityBuilder builder = new EntityBuilder(); + + def "should fire event for each registered listener" () { + given: "multiple listeners, which have to be notified when the builder's method fireEntityCreated is called" + String builtObject = "obj" + String objName = "ObjectName" + + EntityBuilderListener listener1 = Mock() + EntityBuilderListener listener2 = Mock() + + builder + .addEntityBuilderListener(listener1) + .addEntityBuilderListener(listener2) + + when: "the builder's method fireEntityCreated is called" + builder.fireEntityCreated(objName, builtObject) + + then: "the onEntityCreated method of each listener is invoked" + 2 * _.onEntityCreated(objName, builtObject) + } + + def "should create entities from given definition" () { + given: "a groovy script defining entitied to be build" + SimpleClass capturedSimple + + def entityDefinition = """ + import de.triology.blog.testdata.builder.EntityBuilderTest.SimpleClass + import de.triology.blog.testdata.builder.EntityBuilderTest.ComplexClass + + create ComplexClass, "complex", { + prop = "ComplexValue" + simple = create SimpleClass, "simple", { prop = "SimpleValue" } + complex = complex + } + """ + + and: "an entity builder instance with registered listeners" + EntityBuilderListener listener = Mock() + builder.addEntityBuilderListener(listener) + + when: "the script is processed" + builder.build(new StringReader(entityDefinition)) + + then: "the registered listener gets notified for each created object" + 1 * listener.onEntityCreated("simple", { + it.prop == "SimpleValue" + capturedSimple = it + }) + 1 * listener.onEntityCreated("complex", { + it.prop == "ComplexValue" + it.complex == it + it.simple == capturedSimple + }) + + 0 * listener._ + } +} diff --git a/src/test/java/de/triology/blog/testdataloader/FileReaderTest.java b/src/test/java/de/trilogy/blog/testdata/util/FileReaderTest.java similarity index 95% rename from src/test/java/de/triology/blog/testdataloader/FileReaderTest.java rename to src/test/java/de/trilogy/blog/testdata/util/FileReaderTest.java index 4b3f910..c003231 100644 --- a/src/test/java/de/triology/blog/testdataloader/FileReaderTest.java +++ b/src/test/java/de/trilogy/blog/testdata/util/FileReaderTest.java @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader; +package de.trilogy.blog.testdata.util; import org.junit.Test; +import de.triology.blog.testdata.util.FileReader; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; diff --git a/src/test/java/de/triology/blog/testdataloader/EntityDeleterTest.java b/src/test/java/de/triology/blog/testdata/loader/EntityDeleterTest.java similarity index 97% rename from src/test/java/de/triology/blog/testdataloader/EntityDeleterTest.java rename to src/test/java/de/triology/blog/testdata/loader/EntityDeleterTest.java index 3e08156..a52f6f0 100644 --- a/src/test/java/de/triology/blog/testdataloader/EntityDeleterTest.java +++ b/src/test/java/de/triology/blog/testdata/loader/EntityDeleterTest.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader; +package de.triology.blog.testdata.loader; import static org.mockito.AdditionalAnswers.returnsFirstArg; import static org.mockito.Matchers.any; @@ -40,6 +40,8 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import de.triology.blog.testdata.loader.EntityDeleter; + @RunWith(MockitoJUnitRunner.class) public class EntityDeleterTest { diff --git a/src/test/java/de/triology/blog/testdataloader/EntityPersisterTest.java b/src/test/java/de/triology/blog/testdata/loader/EntityPersisterTest.java similarity index 94% rename from src/test/java/de/triology/blog/testdataloader/EntityPersisterTest.java rename to src/test/java/de/triology/blog/testdata/loader/EntityPersisterTest.java index b5e049f..cfd46be 100644 --- a/src/test/java/de/triology/blog/testdataloader/EntityPersisterTest.java +++ b/src/test/java/de/triology/blog/testdata/loader/EntityPersisterTest.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader; +package de.triology.blog.testdata.loader; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -30,6 +30,8 @@ import org.junit.Test; +import de.triology.blog.testdata.loader.EntityPersister; + public class EntityPersisterTest { @Test diff --git a/src/test/java/de/triology/blog/testdataloader/TestDataLoaderTest.java b/src/test/java/de/triology/blog/testdata/loader/TestDataLoaderTest.java similarity index 95% rename from src/test/java/de/triology/blog/testdataloader/TestDataLoaderTest.java rename to src/test/java/de/triology/blog/testdata/loader/TestDataLoaderTest.java index 450697f..0f996ec 100644 --- a/src/test/java/de/triology/blog/testdataloader/TestDataLoaderTest.java +++ b/src/test/java/de/triology/blog/testdata/loader/TestDataLoaderTest.java @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader; +package de.triology.blog.testdata.loader; + +import de.triology.blog.testdata.loader.TestDataLoader; +import de.triology.blog.testdata.loader.testentities.AnotherTestEntity; +import de.triology.blog.testdata.loader.testentities.BasicTestEntity; -import de.triology.blog.testdataloader.testentities.AnotherTestEntity; -import de.triology.blog.testdataloader.testentities.BasicTestEntity; import org.junit.Before; import org.junit.Test; diff --git a/src/test/java/de/triology/blog/testdataloader/demo/Department.java b/src/test/java/de/triology/blog/testdata/loader/it/Department.java similarity index 97% rename from src/test/java/de/triology/blog/testdataloader/demo/Department.java rename to src/test/java/de/triology/blog/testdata/loader/it/Department.java index 89e2c24..1d3a854 100644 --- a/src/test/java/de/triology/blog/testdataloader/demo/Department.java +++ b/src/test/java/de/triology/blog/testdata/loader/it/Department.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.demo; +package de.triology.blog.testdata.loader.it; import javax.persistence.Entity; diff --git a/src/test/java/de/triology/blog/testdataloader/demo/Demo.java b/src/test/java/de/triology/blog/testdata/loader/it/TestDataLoaderIT.java similarity index 96% rename from src/test/java/de/triology/blog/testdataloader/demo/Demo.java rename to src/test/java/de/triology/blog/testdata/loader/it/TestDataLoaderIT.java index 015eb4e..f24f900 100644 --- a/src/test/java/de/triology/blog/testdataloader/demo/Demo.java +++ b/src/test/java/de/triology/blog/testdata/loader/it/TestDataLoaderIT.java @@ -21,13 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.demo; +package de.triology.blog.testdata.loader.it; -import de.triology.blog.testdataloader.TestDataLoader; import org.junit.After; import org.junit.Before; import org.junit.Test; +import de.triology.blog.testdata.loader.TestDataLoader; + import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; @@ -36,7 +37,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; -public class Demo { +public class TestDataLoaderIT { private EntityManager entityManager; private TestDataLoader testDataLoader; diff --git a/src/test/java/de/triology/blog/testdataloader/demo/User.java b/src/test/java/de/triology/blog/testdata/loader/it/User.java similarity index 98% rename from src/test/java/de/triology/blog/testdataloader/demo/User.java rename to src/test/java/de/triology/blog/testdata/loader/it/User.java index f915491..7b21a35 100644 --- a/src/test/java/de/triology/blog/testdataloader/demo/User.java +++ b/src/test/java/de/triology/blog/testdata/loader/it/User.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.demo; +package de.triology.blog.testdata.loader.it; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/src/test/java/de/triology/blog/testdataloader/testentities/AnotherTestEntity.java b/src/test/java/de/triology/blog/testdata/loader/testentities/AnotherTestEntity.java similarity index 95% rename from src/test/java/de/triology/blog/testdataloader/testentities/AnotherTestEntity.java rename to src/test/java/de/triology/blog/testdata/loader/testentities/AnotherTestEntity.java index d11a923..ed0a8e9 100644 --- a/src/test/java/de/triology/blog/testdataloader/testentities/AnotherTestEntity.java +++ b/src/test/java/de/triology/blog/testdata/loader/testentities/AnotherTestEntity.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.testentities; +package de.triology.blog.testdata.loader.testentities; public class AnotherTestEntity { diff --git a/src/test/java/de/triology/blog/testdataloader/testentities/BaseClass.java b/src/test/java/de/triology/blog/testdata/loader/testentities/BaseClass.java similarity index 96% rename from src/test/java/de/triology/blog/testdataloader/testentities/BaseClass.java rename to src/test/java/de/triology/blog/testdata/loader/testentities/BaseClass.java index 37f8bce..724b2b1 100644 --- a/src/test/java/de/triology/blog/testdataloader/testentities/BaseClass.java +++ b/src/test/java/de/triology/blog/testdata/loader/testentities/BaseClass.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.testentities; +package de.triology.blog.testdata.loader.testentities; import javax.persistence.MappedSuperclass; diff --git a/src/test/java/de/triology/blog/testdataloader/testentities/BasicTestEntity.java b/src/test/java/de/triology/blog/testdata/loader/testentities/BasicTestEntity.java similarity index 97% rename from src/test/java/de/triology/blog/testdataloader/testentities/BasicTestEntity.java rename to src/test/java/de/triology/blog/testdata/loader/testentities/BasicTestEntity.java index 3017026..51da63b 100644 --- a/src/test/java/de/triology/blog/testdataloader/testentities/BasicTestEntity.java +++ b/src/test/java/de/triology/blog/testdata/loader/testentities/BasicTestEntity.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.testentities; +package de.triology.blog.testdata.loader.testentities; import java.util.Date; diff --git a/src/test/java/de/triology/blog/testdataloader/testentities/InheritingEntity.java b/src/test/java/de/triology/blog/testdata/loader/testentities/InheritingEntity.java similarity index 95% rename from src/test/java/de/triology/blog/testdataloader/testentities/InheritingEntity.java rename to src/test/java/de/triology/blog/testdata/loader/testentities/InheritingEntity.java index aa7d206..8b35b25 100644 --- a/src/test/java/de/triology/blog/testdataloader/testentities/InheritingEntity.java +++ b/src/test/java/de/triology/blog/testdata/loader/testentities/InheritingEntity.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.testentities; +package de.triology.blog.testdata.loader.testentities; public class InheritingEntity extends BaseClass { diff --git a/src/test/java/de/triology/blog/testdataloader/testentities/TestEntityWithToManyRelationship.java b/src/test/java/de/triology/blog/testdata/loader/testentities/TestEntityWithToManyRelationship.java similarity index 96% rename from src/test/java/de/triology/blog/testdataloader/testentities/TestEntityWithToManyRelationship.java rename to src/test/java/de/triology/blog/testdata/loader/testentities/TestEntityWithToManyRelationship.java index 6f49a34..b4e0017 100644 --- a/src/test/java/de/triology/blog/testdataloader/testentities/TestEntityWithToManyRelationship.java +++ b/src/test/java/de/triology/blog/testdata/loader/testentities/TestEntityWithToManyRelationship.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.testentities; +package de.triology.blog.testdata.loader.testentities; import java.util.Collection; diff --git a/src/test/java/de/triology/blog/testdataloader/testentities/TestEntityWithToOneRelationship.java b/src/test/java/de/triology/blog/testdata/loader/testentities/TestEntityWithToOneRelationship.java similarity index 97% rename from src/test/java/de/triology/blog/testdataloader/testentities/TestEntityWithToOneRelationship.java rename to src/test/java/de/triology/blog/testdata/loader/testentities/TestEntityWithToOneRelationship.java index b50583d..ba10ad8 100644 --- a/src/test/java/de/triology/blog/testdataloader/testentities/TestEntityWithToOneRelationship.java +++ b/src/test/java/de/triology/blog/testdata/loader/testentities/TestEntityWithToOneRelationship.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package de.triology.blog.testdataloader.testentities; +package de.triology.blog.testdata.loader.testentities; public class TestEntityWithToOneRelationship { diff --git a/src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java b/src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java deleted file mode 100644 index 5ec9d16..0000000 --- a/src/test/java/de/triology/blog/testdataloader/EntityBuilderTest.java +++ /dev/null @@ -1,241 +0,0 @@ -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package de.triology.blog.testdataloader; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.List; -import java.util.NoSuchElementException; - -import org.apache.commons.lang3.time.DateUtils; -import org.junit.Before; -import org.junit.Test; - -import de.triology.blog.testdataloader.testentities.AnotherTestEntity; -import de.triology.blog.testdataloader.testentities.BasicTestEntity; -import de.triology.blog.testdataloader.testentities.InheritingEntity; -import de.triology.blog.testdataloader.testentities.TestEntityWithToManyRelationship; -import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelationship; - -public class EntityBuilderTest { - - private EntityBuilder builder; - private EntityStore entityStore; - - @Before - public void setUp() throws Exception { - builder = EntityBuilder.newBuilder(); - callBuildEntitiesWithFile("tests/testEntityDefinitions.groovy"); - } - - private void callBuildEntitiesWithFile(final String file) throws FileNotFoundException { - entityStore = builder.build(FileReader.create(file)); - } - - @Test - public void getsCreatedEntityByName() throws Exception { - final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); - assertNotNull(entity); - } - - @Test(expected = NoSuchElementException.class) - public void getEntityByNameFailsForNonexistingEntity() throws Exception { - entityStore.getEntityByName("notExisting", BasicTestEntity.class); - } - - @Test(expected = IllegalArgumentException.class) - public void getEntityByNameFailsIfPassesClassDoesNotMatch() throws Exception { - entityStore.getEntityByName("basicEntity", AnotherTestEntity.class); - } - - @Test - public void createsEntityFromDsl() throws Exception { - assertEntityOfClassWasBuilt("basicEntity", BasicTestEntity.class); - } - - @Test - public void createsEntityThatUsesFieldFromMappedSuperclass() throws Exception { - callBuildEntitiesWithFile("tests/mappedSuperclass.groovy"); - assertEntityOfClassWasBuilt("inherited", InheritingEntity.class); - } - - @Test - public void createsMultipleEntitiesFromDsl() throws Exception { - assertEntityOfClassWasBuilt("secondBasicEntity", BasicTestEntity.class); - assertEntityOfClassWasBuilt("entityOfAnotherClass", AnotherTestEntity.class); - } - - private void assertEntityOfClassWasBuilt(final String entityName, final Class clazz) { - final T entity = entityStore.getEntityByName(entityName, clazz); - assertNotNull("entity of name " + entityName + " was not built", entity); - assertEquals(clazz, entity.getClass()); - } - - @Test - public void setsStringProperty() throws Exception { - final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); - assertEquals("a string value", entity.getStringProperty()); - } - - @Test - public void setsIntegerProperty() throws Exception { - final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); - assertEquals(5, (int) entity.getIntegerProperty()); - } - - @Test - public void setProgrammaticallyCreatedDateProperty() throws Exception { - final BasicTestEntity entity = entityStore.getEntityByName("basicEntity", BasicTestEntity.class); - final Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.DAY_OF_MONTH, 18); - calendar.set(Calendar.MONTH, Calendar.NOVEMBER); - calendar.set(Calendar.YEAR, 2015); - assertTrue(DateUtils.isSameDay(calendar.getTime(), entity.getDateProperty())); - } - - @Test - public void buildsReferencedEntityInPlace() throws Exception { - final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("entityWithToOneRelationship", - TestEntityWithToOneRelationship.class); - assertEntityOfClassWasBuilt("referencedInstance", BasicTestEntity.class); - final BasicTestEntity referencedEntity = entityStore.getEntityByName("referencedInstance", BasicTestEntity.class); - assertSame(referencedEntity, entity.getReferencedEntity()); - } - - @Test - public void setsPropertiesOfEntitiesBuiltInPlace() throws Exception { - final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("entityWithToOneRelationship", - TestEntityWithToOneRelationship.class); - final BasicTestEntity referencedEntity = entity.getReferencedEntity(); - assertEquals("string in referenced entity", referencedEntity.getStringProperty()); - assertEquals(222, (int) referencedEntity.getIntegerProperty()); - } - - @Test - public void buildEntitiesWithArbitraryNesting() throws Exception { - final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("deeplyNestedEntities", - TestEntityWithToOneRelationship.class); - assertSame(entityStore.getEntityByName("nest1", TestEntityWithToOneRelationship.class), - entity.getTestEntityWithToOneRelationship()); - assertSame(entityStore.getEntityByName("nest2", TestEntityWithToOneRelationship.class), - entity.getTestEntityWithToOneRelationship().getTestEntityWithToOneRelationship()); - assertSame(entityStore.getEntityByName("nest3", BasicTestEntity.class), - entity.getTestEntityWithToOneRelationship().getTestEntityWithToOneRelationship().getReferencedEntity()); - assertEquals("deeply nested string", entityStore.getEntityByName("nest3", BasicTestEntity.class).getStringProperty()); - } - - @Test - public void resolvesReferences() throws Exception { - final TestEntityWithToOneRelationship entity = entityStore.getEntityByName("entityReferencingPreviouslyCreatedEntity", - TestEntityWithToOneRelationship.class); - assertSame(entityStore.getEntityByName("secondBasicEntity", BasicTestEntity.class), entity.getReferencedEntity()); - } - - @Test(expected = EntityBuildingException.class) - public void failsIfReferencedEntityDoesNotExist() throws Exception { - callBuildEntitiesWithFile("tests/failingBecauseOfMissingReferencedEntity.groovy"); - } - - @Test(expected = EntityBuildingException.class) - public void failsIfAnEntityNameHasAlreadyBeenUsed() throws Exception { - callBuildEntitiesWithFile("tests/failingBecauseOfReusedName.groovy"); - } - - @Test - public void setsCollectionOfReferencedEntities() throws Exception { - final TestEntityWithToManyRelationship entity = entityStore.getEntityByName("entityWithCollection", - TestEntityWithToManyRelationship.class); - final Collection toManyRelationship = entity.getToManyRelationship(); - assertEquals(2, toManyRelationship.size()); - BasicTestEntity referencedEntity1 = null; - BasicTestEntity referencedEntity2 = null; - for (final BasicTestEntity basicTestEntity : toManyRelationship) { - if (referencedEntity1 == null) { - referencedEntity1 = basicTestEntity; - } else { - referencedEntity2 = basicTestEntity; - } - } - assertNotSame(referencedEntity1, referencedEntity2); - assert referencedEntity1 != null; - assertEquals(5, (int) referencedEntity1.getIntegerProperty()); - assert referencedEntity2 != null; - assertEquals(5, (int) referencedEntity2.getIntegerProperty()); - } - - @Test - public void notifiesEntityCreatedListenerInTheOrderOfEntityCreation() throws Exception { - final List entitiesInOrderOfCreation = new ArrayList(); - builder.addEntityCreatedListener(new EntityCreatedListener() { - public void onEntityCreated(final String name, final Object entity) { - entitiesInOrderOfCreation.add(entity); - } - }); - callBuildEntitiesWithFile("tests/testOrderOfEntityCreatedListenerNotifications.groovy"); - assertEquals(4, entitiesInOrderOfCreation.size()); - assertEquals(BasicTestEntity.class, entitiesInOrderOfCreation.get(0).getClass()); - assertEquals(TestEntityWithToOneRelationship.class, entitiesInOrderOfCreation.get(1).getClass()); - assertEquals(AnotherTestEntity.class, entitiesInOrderOfCreation.get(2).getClass()); - assertEquals(TestEntityWithToOneRelationship.class, entitiesInOrderOfCreation.get(3).getClass()); - } - - @Test(expected = NoSuchElementException.class) - public void clearsEntities() throws Exception { - try { - entityStore.getEntityByName("basicEntity", BasicTestEntity.class); - } catch (final NoSuchElementException e) { - e.printStackTrace(); - fail("basicEntity already was not available before calling clearEntityCacheAndDatabase"); - } - - entityStore.clear(); - entityStore.getEntityByName("basicEntity", BasicTestEntity.class); - } - - @Test - public void builderCreatesNewStoreForEachBuildAttempt() throws FileNotFoundException { - final EntityStore oldStore = EntityBuilder.newBuilder().build(FileReader.create("tests/testEntityDefinitions.groovy")); - final EntityStore newStore = EntityBuilder.newBuilder().build(FileReader.create("tests/testEntityDefinitions.groovy")); - - assertNotEquals(oldStore, newStore); - - final BasicTestEntity oldEntity = oldStore.getEntityByName("basicEntity", BasicTestEntity.class); - assertNotNull(oldEntity); - - final BasicTestEntity newEntity = newStore.getEntityByName("basicEntity", BasicTestEntity.class); - assertNotNull(newEntity); - - assertNotEquals(oldEntity, newEntity); - } -} \ No newline at end of file diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml index a476c4a..061b0a1 100644 --- a/src/test/resources/META-INF/persistence.xml +++ b/src/test/resources/META-INF/persistence.xml @@ -1,29 +1,3 @@ - - diff --git a/src/test/resources/demo/testData.groovy b/src/test/resources/demo/testData.groovy index 9124135..c4861ae 100644 --- a/src/test/resources/demo/testData.groovy +++ b/src/test/resources/demo/testData.groovy @@ -1,29 +1,5 @@ -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -import de.triology.blog.testdataloader.demo.Department - -import de.triology.blog.testdataloader.demo.User +import de.triology.blog.testdata.loader.it.Department +import de.triology.blog.testdata.loader.it.User create User, 'Peter', { id = 123 diff --git a/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy b/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy index 4e9d0de..3b53eaf 100644 --- a/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy +++ b/src/test/resources/tests/failingBecauseOfMissingReferencedEntity.groovy @@ -1,27 +1,4 @@ -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelationship +import de.triology.blog.testdata.loader.testentities.TestEntityWithToOneRelationship create TestEntityWithToOneRelationship, 'entityReferencingANonexistingEntity', { referencedEntity = notExistingReference diff --git a/src/test/resources/tests/failingBecauseOfReusedName.groovy b/src/test/resources/tests/failingBecauseOfReusedName.groovy index 1800796..e293712 100644 --- a/src/test/resources/tests/failingBecauseOfReusedName.groovy +++ b/src/test/resources/tests/failingBecauseOfReusedName.groovy @@ -1,27 +1,4 @@ -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -import de.triology.blog.testdataloader.testentities.AnotherTestEntity +import de.triology.blog.testdata.loader.testentities.AnotherTestEntity import de.triology.blog.testdataloader.testentities.BasicTestEntity create BasicTestEntity, 'nameThatIsUsedTwoTimes', {} diff --git a/src/test/resources/tests/mappedSuperclass.groovy b/src/test/resources/tests/mappedSuperclass.groovy index 9203627..1292d57 100644 --- a/src/test/resources/tests/mappedSuperclass.groovy +++ b/src/test/resources/tests/mappedSuperclass.groovy @@ -1,30 +1,4 @@ -package tests - -import de.triology.blog.testdataloader.testentities.InheritingEntity - -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ +import de.triology.blog.testdata.loader.testentities.InheritingEntity create(InheritingEntity, "inherited") { inheritedField = "this Field is privately defined in the superclass" diff --git a/src/test/resources/tests/testEntityDefinitions.groovy b/src/test/resources/tests/testEntityDefinitions.groovy index cb6a989..aa6839d 100644 --- a/src/test/resources/tests/testEntityDefinitions.groovy +++ b/src/test/resources/tests/testEntityDefinitions.groovy @@ -1,30 +1,7 @@ -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -import de.triology.blog.testdataloader.testentities.AnotherTestEntity -import de.triology.blog.testdataloader.testentities.BasicTestEntity -import de.triology.blog.testdataloader.testentities.TestEntityWithToManyRelationship -import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelationship +import de.triology.blog.testdata.loader.testentities.AnotherTestEntity +import de.triology.blog.testdata.loader.testentities.BasicTestEntity +import de.triology.blog.testdata.loader.testentities.TestEntityWithToManyRelationship +import de.triology.blog.testdata.loader.testentities.TestEntityWithToOneRelationship import java.text.SimpleDateFormat diff --git a/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy b/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy index b68d723..ec918f2 100644 --- a/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy +++ b/src/test/resources/tests/testOrderOfEntityCreatedListenerNotifications.groovy @@ -1,29 +1,6 @@ -/** - * MIT License - * - * Copyright (c) 2016 TRIOLOGY GmbH - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -import de.triology.blog.testdataloader.testentities.AnotherTestEntity -import de.triology.blog.testdataloader.testentities.BasicTestEntity -import de.triology.blog.testdataloader.testentities.TestEntityWithToOneRelationship +import de.triology.blog.testdata.loader.testentities.AnotherTestEntity +import de.triology.blog.testdata.loader.testentities.BasicTestEntity +import de.triology.blog.testdata.loader.testentities.TestEntityWithToOneRelationship create TestEntityWithToOneRelationship, 'entityWithToOneRelationship', { referencedEntity = create BasicTestEntity, 'referencedInstance', { From 438e8dfbb079b12ff249d36e0907ffa6f82a46c5 Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Wed, 15 Nov 2017 10:55:52 +0100 Subject: [PATCH 4/8] applied @PackageScoped to EntityPersister --- .../de/triology/blog/testdata/loader/EntityPersister.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/groovy/de/triology/blog/testdata/loader/EntityPersister.groovy b/src/main/groovy/de/triology/blog/testdata/loader/EntityPersister.groovy index ed2f7f8..a8a967a 100644 --- a/src/main/groovy/de/triology/blog/testdata/loader/EntityPersister.groovy +++ b/src/main/groovy/de/triology/blog/testdata/loader/EntityPersister.groovy @@ -26,10 +26,12 @@ package de.triology.blog.testdata.loader import javax.persistence.EntityManager import de.triology.blog.testdata.builder.EntityBuilderListener +import groovy.transform.PackageScope /** * An EntityCreatedListener that persists created entities. */ +@PackageScope class EntityPersister implements EntityBuilderListener { private EntityManager entityManager From c1b7cc724b7e5d583ac404979672b299cca4413f Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Wed, 15 Nov 2017 10:57:43 +0100 Subject: [PATCH 5/8] IT tests are now handled by failsafe plugin. gmavenplus-plugin is now used to compile groovy code --- pom.xml | 90 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 6504ef5..fb8ea45 100644 --- a/pom.xml +++ b/pom.xml @@ -91,19 +91,84 @@ - + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + [1.6,) + + compileTests + + + + + + + + + + + + + + org.apache.maven.plugins maven-surefire-plugin 2.19.1 - - de.triology.blog.testdataloader.demo.Demo - + + + **/Test* + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.19.1 + + ${project.build.directory}/surefire-reports + + + + + integration-test + verify + + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 1.6 + + + + addSources + addTestSources + compile + compileTests + + + + + org.codehaus.mojo build-helper-maven-plugin @@ -133,22 +198,6 @@ org.apache.maven.plugins maven-compiler-plugin 3.5.1 - true - - groovy-eclipse-compiler - - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.2-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.4.3-01 - - @@ -220,6 +269,7 @@ + From 7b67cc4276e9e74a580dd6e6ad8ca1c4163ad050 Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Wed, 15 Nov 2017 11:02:31 +0100 Subject: [PATCH 6/8] comment fixed --- .../de/triology/blog/testdata/builder/EntityBuilderTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy b/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy index 49c7532..1d5dccd 100755 --- a/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy +++ b/src/test/groovy/de/triology/blog/testdata/builder/EntityBuilderTest.groovy @@ -80,7 +80,7 @@ class EntityBuilderTest extends Specification { when: "the script is processed" builder.build(new StringReader(entityDefinition)) - then: "the registered listener gets notified for each created object" + then: "the registered listener get notified for each created object" 1 * listener.onEntityCreated("simple", { it.prop == "SimpleValue" capturedSimple = it From eaecd58abe49806c347074c347215405f497d580 Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Thu, 23 Nov 2017 20:24:56 +0100 Subject: [PATCH 7/8] Comments for parameters added. In addition the resolveStrategy for the rehydrated closure set to DELEGATE_FIRST --- .../triology/blog/testdata/builder/EntityBuilderDsl.groovy | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderDsl.groovy b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderDsl.groovy index dbff3fd..4a39cbb 100755 --- a/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderDsl.groovy +++ b/src/main/groovy/de/triology/blog/testdata/builder/EntityBuilderDsl.groovy @@ -37,9 +37,9 @@ class EntityBuilderDsl { * Creates an Instance of the specified entityClass, registers it under the specified entityName and applies the * specified entityData definition * - * @param entityClass - * @param entityName - * @param entityData + * @param entityClass - the type defining the entity + * @param entityName - the name to reference the entity e.g. in another call to create + * @param entityData - a Closure used to build the entity * @return the created entity */ public T create(@DelegatesTo.Target Class entityClass, String entityName, @@ -48,6 +48,7 @@ class EntityBuilderDsl { T entity = createEntityInstance(entityName, entityClass) def rehydrated = entityData.rehydrate(entity, this, this) + rehydrated.resolveStrategy = Closure.DELEGATE_FIRST rehydrated.call() builder.fireEntityCreated(entityName, entity) From 7043e3f22b75bd96d1c4168ec30000c369fefafc Mon Sep 17 00:00:00 2001 From: Dimitrij Drus Date: Thu, 23 Nov 2017 20:27:26 +0100 Subject: [PATCH 8/8] DSLD file for eclipse added --- .../resources/dsld/EclipseEntityBuilder.dsld | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 src/main/resources/dsld/EclipseEntityBuilder.dsld diff --git a/src/main/resources/dsld/EclipseEntityBuilder.dsld b/src/main/resources/dsld/EclipseEntityBuilder.dsld new file mode 100755 index 0000000..f51bb4b --- /dev/null +++ b/src/main/resources/dsld/EclipseEntityBuilder.dsld @@ -0,0 +1,29 @@ +/* + * this is a DSL descriptor which supports the creation of groovy EntityBuilder based scripts + * + * @author Dimitrij Drus + */ + +contribute(isScript()) { + provider = "Entity Builder DSL" + + method name: "create", params: [entityClass: Class, entityName: String, entityData: Closure], + declaringType: 'de.triology.blog.testdata.builder.EntityBuilderDsl' +} + +contribute(isScript() & enclosingCallName("create") & inClosure()) { + provider = "Entity Builder DSL" + + Class type = getReferencedType(enclosingNode) + + if(type) { + delegatesTo(type) + setDelegateType(type.name) + } +} + +Class getReferencedType(node) { + def expressions = node?.arguments?.expressions + return expressions ? expressions[0].type.getTypeClass() : null +} +