You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/07/31 07:25:48 UTC

[isis] branch master updated: ISIS-2794: rework tests to also test the tx rollback case

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new e7d7c3d  ISIS-2794: rework tests to also test the tx rollback case
e7d7c3d is described below

commit e7d7c3d936ef537ebae412679c2008797c6161b2
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Jul 31 09:25:36 2021 +0200

    ISIS-2794: rework tests to also test the tx rollback case
---
 .../LifecycleEventPublishingTestAbstract.java      |  14 +++
 .../publishing/PropertyPublishingTestAbstract.java |  14 ++-
 .../publishing/PublishingTestAbstract.java         |   2 +-
 .../publishing/PublishingTestFactoryAbstract.java  | 137 ++++++++++++++-------
 .../publishing/PublishingTestFactoryJdo.java       |  64 +++++-----
 .../publishing/PublishingTestFactoryJpa.java       |  68 +++++-----
 6 files changed, 183 insertions(+), 116 deletions(-)

diff --git a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/LifecycleEventPublishingTestAbstract.java b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/LifecycleEventPublishingTestAbstract.java
index fa67dcc..50aa07f 100644
--- a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/LifecycleEventPublishingTestAbstract.java
+++ b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/LifecycleEventPublishingTestAbstract.java
@@ -90,6 +90,9 @@ extends PublishingTestAbstract {
 
             switch(changeScenario) {
             case ENTITY_CREATION:
+                //TODO what is there to verify?
+                return;
+            case ENTITY_PERSISTING:
 
                 assertHasPersistingLifecycleEvents(bookSample1);
                 //assertHasPersistedLifecycleEvents(Can.empty()); //TODO what is expected empty or not?
@@ -128,6 +131,17 @@ extends PublishingTestAbstract {
 
                 //assertHasCreatedLifecycleEvents(bookSample1); //FIXME creation events not triggered
                 assertHasLoadedLifecycleEvents(Can.empty());
+                assertHasPersistingLifecycleEvents(Can.empty());
+                assertHasPersistedLifecycleEvents(Can.empty());
+                assertHasUpdatingLifecycleEvents(Can.empty());
+                assertHasUpdatedLifecycleEvents(Can.empty());
+                assertHasRemovingLifecycleEvents(Can.empty());
+                return;
+
+            case ENTITY_PERSISTING:
+
+                assertHasCreatedLifecycleEvents(Can.empty()); // creation events are deliberately not triggered for this test
+                assertHasLoadedLifecycleEvents(Can.empty());
                 assertHasPersistingLifecycleEvents(bookSample1);
                 assertHasPersistedLifecycleEvents(bookSample1);
                 assertHasUpdatingLifecycleEvents(Can.empty());
diff --git a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PropertyPublishingTestAbstract.java b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PropertyPublishingTestAbstract.java
index 8090fca..f5d1f08 100644
--- a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PropertyPublishingTestAbstract.java
+++ b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PropertyPublishingTestAbstract.java
@@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.testdomain.publishing.PublishingTestFactoryAbstract.ChangeScenario;
 import org.apache.isis.testdomain.publishing.PublishingTestFactoryAbstract.VerificationStage;
 import org.apache.isis.testdomain.publishing.subscriber.EntityPropertyChangeSubscriberForTesting;
@@ -62,24 +63,27 @@ extends PublishingTestAbstract {
 
             switch(changeScenario) {
             case ENTITY_CREATION:
+                return; // factory-service does not trigger property publishing
+            case ENTITY_PERSISTING:
                 assertContainsPropertyChangeEntries(Can.of(
                         formatPersistenceStandardSpecificCapitalize("%s Book/name: '[NEW]' -> 'Sample Book'")));
-                break;
+                return;
             case PROPERTY_UPDATE:
                 assertHasPropertyChangeEntries(Can.of(
                         formatPersistenceStandardSpecificCapitalize("%s Book/name: 'Sample Book' -> 'Book #2'")));
-                break;
+                return;
             case ACTION_INVOCATION:
                 assertHasPropertyChangeEntries(Can.of(
                         formatPersistenceStandardSpecificCapitalize("%s Book/price: '99.0' -> '198.0'")));
-                break;
+                return;
             case ENTITY_REMOVAL:
                 assertContainsPropertyChangeEntries(Can.of(
                         formatPersistenceStandardSpecificCapitalize("%s Book/name: 'Sample Book' -> '[DELETED]'")));
-                break;
+                return;
+            default:
+                throw _Exceptions.unmatchedCase(changeScenario);
             }
 
-            break;
         default:
             // if hitting this, the caller is requesting a verification stage, we are providing no case for
             fail(String.format("internal error, stage not verified: %s", verificationStage));
diff --git a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PublishingTestAbstract.java b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PublishingTestAbstract.java
index 0e0c82f..454607a 100644
--- a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PublishingTestAbstract.java
+++ b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/publishing/PublishingTestAbstract.java
@@ -19,7 +19,7 @@ implements HasPersistenceStandard {
 
     protected abstract boolean supportsProgrammaticTesting(ChangeScenario changeScenario);
 
-    @TestFactory @DisplayName("Entity Creation")
+    @TestFactory @DisplayName("Entity Creation (FactoryService)")
     final List<DynamicTest> generateTestsForCreation() {
         return generateTests(ChangeScenario.ENTITY_CREATION);
     }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryAbstract.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryAbstract.java
index f6eb0d5..5e58d80 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryAbstract.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryAbstract.java
@@ -36,9 +36,11 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
 
 import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.applib.services.wrapper.DisabledException;
 import org.apache.isis.applib.services.xactn.TransactionService;
 import org.apache.isis.applib.services.xactn.TransactionState;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.functional.Result;
 import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.debug._Probe;
@@ -65,7 +67,8 @@ public abstract class PublishingTestFactoryAbstract {
     /** what kind of entity change is under test */
     @RequiredArgsConstructor @Getter
     public static enum ChangeScenario {
-        ENTITY_CREATION("creation", true),
+        ENTITY_CREATION("creation via factory-service", true),
+        ENTITY_PERSISTING("persisting", true),
         ENTITY_LOADING("loading", true),
         PROPERTY_UPDATE("property update", false),
         ACTION_INVOCATION("action invocation", false),
@@ -89,13 +92,21 @@ public abstract class PublishingTestFactoryAbstract {
                 }
                 return this;
             }
+
+            public void header() {
+                log("---------------------------------------------------------");
+            }
+
+            public void footer() {
+                log("---------------------------------------------------------");
+            }
         }
 
         private final @NonNull String displayName;
         private final @NonNull ChangeScenario scenario;
+        private final @NonNull Optional<Class<? extends Throwable>> expectedException;
         private final @NonNull Runnable given;
         private final @NonNull BiConsumer<ChangeScenario, VerificationStage> verifier;
-        private final @NonNull VerificationStage transactionCompletionStage;
 
         private final TraceLog traceLog = new TraceLog();
         private final List<Throwable> verificationErrors = _Lists.newConcurrentList();
@@ -107,11 +118,12 @@ public abstract class PublishingTestFactoryAbstract {
         }
 
         public void runVerify(final VerificationStage verificationStage) {
-            traceLog.log("4.? verify %s", verificationStage);
             try {
                 verifier.accept(scenario, verificationStage);
+                traceLog.log("v. verify %s -> %s", verificationStage, "success");
             } catch (Throwable e) {
                 verificationErrors.add(e);
+                traceLog.log("v. verify %s -> %s", verificationStage, "failure");
             }
         }
 
@@ -135,15 +147,11 @@ public abstract class PublishingTestFactoryAbstract {
             traceLog.log("2.4 book's price has been doubled");
         }
 
-        public void runPostCommitVerify() {
-            runVerify(transactionCompletionStage);
-        }
-
     }
 
     @FunctionalInterface
     private static interface PublishingTestRunner {
-        boolean run(PublishingTestContext context) throws Exception;
+        void run(PublishingTestContext context) throws Exception;
     }
 
     /**
@@ -158,21 +166,28 @@ public abstract class PublishingTestFactoryAbstract {
 
         /** transaction end boundary (pre) */
         @EventListener(TransactionBeforeCompletionEvent.class)
-        public void onPreCommit(final TransactionBeforeCompletionEvent event) {
+        public void onPreCompletion(final TransactionBeforeCompletionEvent event) {
             _Probe.errOut("=== TRANSACTION before completion");
             if(testContext!=null) {
-                testContext.getTraceLog().log("3. pre-commit event is occurring");
+                testContext.getTraceLog().log("3.1 pre-commit event is occurring");
                 testContext.runVerify(VerificationStage.PRE_COMMIT);
             }
         }
 
         /** transaction end boundary (post) */
         @EventListener(TransactionAfterCompletionEvent.class)
-        public void onPreCommit(final TransactionAfterCompletionEvent event) {
+        public void onPostCompletion(final TransactionAfterCompletionEvent event) {
             _Probe.errOut("=== TRANSACTION after completion");
             if(testContext!=null) {
                 try {
-                    testContext.runPostCommitVerify();
+                    if(event.isCommitted()) {
+                        testContext.getTraceLog().log("3.2 post-commit event is occurring");
+                        testContext.runVerify(VerificationStage.POST_COMMIT);
+                    } else {
+                        testContext.getTraceLog().log("3.2 rollback event is occurring");
+                        testContext.runVerify(VerificationStage.FAILURE_CASE);
+                    }
+
                 } finally {
                     unbind(testContext);
                 }
@@ -200,7 +215,6 @@ public abstract class PublishingTestFactoryAbstract {
 
     // -- CREATE DYNAMIC TESTS
 
-    @Deprecated //FIXME not deprecated - simplify and trigger the verification stages automatically, not declaratively
     public final List<DynamicTest> generateTests(
             final ChangeScenario changeScenario,
             final boolean includeProgrammatic,
@@ -214,12 +228,11 @@ public abstract class PublishingTestFactoryAbstract {
                 .add(publishingTest(
                         PublishingTestContext.of("Programmatic",
                                 changeScenario,
-                                given, verifier, VerificationStage.POST_COMMIT),
-                        VerificationStage.POST_INTERACTION,
+                                Optional.empty(),
+                                given, verifier),
                         this::programmaticExecution));
         }
 
-
         if(changeScenario == ChangeScenario.PROPERTY_UPDATE
                 || changeScenario == ChangeScenario.ACTION_INVOCATION) {
 
@@ -227,33 +240,32 @@ public abstract class PublishingTestFactoryAbstract {
                 .add(publishingTest(
                         PublishingTestContext.of("Interaction Api",
                                 changeScenario,
-                                given, verifier, VerificationStage.POST_COMMIT),
-                        VerificationStage.POST_INTERACTION,
+                                Optional.empty(),
+                                given, verifier),
                         this::interactionApiExecution))
                 .add(publishingTest(
                         PublishingTestContext.of("Wrapper Sync w/o Rules",
                                 changeScenario,
-                                given, verifier, VerificationStage.POST_COMMIT),
-                        VerificationStage.POST_INTERACTION,
+                                Optional.empty(),
+                                given, verifier),
                         this::wrapperSyncExecutionNoRules))
 //                    .add(publishingTest(
 //                            PublishingTestContext.of("Wrapper Async w/o Rules",
 //                                  changeScenario,
-//                                  given, verifier, VerificationStage.POST_COMMIT),
-//                            VerificationStage.POST_INTERACTION,
+//                                  given, verifier),
 //                            this::wrapperAsyncExecutionNoRules))
                 .add(publishingTest(
                         PublishingTestContext.of("Wrapper Sync w/ Rules (expected to fail w/ DisabledException)",
                                 changeScenario,
-                                given, verifier, VerificationStage.FAILURE_CASE),
-                        VerificationStage.POST_INTERACTION,
-                        this::wrapperSyncExecutionWithFailure))
+                                Optional.of(DisabledException.class),
+                                given, verifier),
+                        this::wrapperSyncExecutionWithRules))
 //                    .add(publishingTest(
 //                            PublishingTestContext.of("Wrapper Async w/ Rules (expected to fail w/ DisabledException)",
 //                                    changeScenario,
-//                                    given, verifier, VerificationStage.FAILURE_CASE),
-//                            VerificationStage.POST_INTERACTION,
-//                            this::wrapperAsyncExecutionWithFailure))
+//                                    Optional.of(DisabledException.class),
+//                                    given, verifier),
+//                            this::wrapperAsyncExecutionWithRules))
                 ;
 
         };
@@ -271,45 +283,48 @@ public abstract class PublishingTestFactoryAbstract {
     protected abstract void setupEntity(PublishingTestContext context);
 
     /** a test - method is embedded in its own interaction and transaction */
-    protected abstract boolean programmaticExecution(PublishingTestContext context);
+    protected abstract void programmaticExecution(PublishingTestContext context);
 
     /** a test - method is embedded in its own interaction and transaction */
-    protected abstract boolean interactionApiExecution(PublishingTestContext context);
+    protected abstract void interactionApiExecution(PublishingTestContext context);
 
     /** a test - method is embedded in its own interaction and transaction */
-    protected abstract boolean wrapperSyncExecutionNoRules(PublishingTestContext context);
+    protected abstract void wrapperSyncExecutionNoRules(PublishingTestContext context);
 
     /** a test - method is embedded in its own interaction and transaction */
     @Deprecated // not deprecated - but we don't know yet how to test
     //XXX requires the AsyncExecution to run in its own interaction and transaction,
     // ideally to be enforced by running on a different thread, yet we are using the fork-join pool
     // which provides no such guarantee
-    protected abstract boolean wrapperAsyncExecutionNoRules(PublishingTestContext context) throws InterruptedException, ExecutionException, TimeoutException;
+    protected abstract void wrapperAsyncExecutionNoRules(PublishingTestContext context) throws InterruptedException, ExecutionException, TimeoutException;
 
     /** a test - method is embedded in its own interaction and transaction */
-    protected abstract boolean wrapperSyncExecutionWithFailure(PublishingTestContext context);
+    protected abstract void wrapperSyncExecutionWithRules(PublishingTestContext context);
 
     /** a test - method is embedded in its own interaction and transaction */
-    protected abstract boolean wrapperAsyncExecutionWithFailure(PublishingTestContext context);
+    protected abstract void wrapperAsyncExecutionWithRules(PublishingTestContext context);
 
 
     // -- HELPER
 
     private final DynamicTest publishingTest(
             final PublishingTestContext testContext,
-            final VerificationStage onSuccess,
             final PublishingTestRunner testRunner) {
 
         val displayName = String.format("%s (%s)",
                 testContext.getDisplayName(),
                 testContext.getScenario().getDisplayName());
 
+        val onSuccess = VerificationStage.POST_INTERACTION;
+        val onFailure = VerificationStage.FAILURE_CASE;
+
         return dynamicTest(displayName, ()->{
 
             val traceLog = testContext.getTraceLog();
 
             xrayAddTest(displayName);
 
+            traceLog.header();
             traceLog.log("0. enter test %s", displayName);
 
             try {
@@ -327,28 +342,62 @@ public abstract class PublishingTestFactoryAbstract {
                 assertFalse(getInteractionService().isInInteraction());
                 assert_no_initial_tx_context();
 
-                final boolean isExpectedToRunSuccesful = getInteractionService().callAnonymous(()->{
+//                val result = getInteractionService().callAnonymous(()->{
+//                    val currentInteraction = getInteractionService().currentInteraction();
+//                    xrayEnterInteraction(currentInteraction);
+//
+//                    Result<Boolean> result;
+//                    try {
+//                        testRunner.run(testContext);
+//                        result = Result.success(true);
+//                    } catch (Exception e) {
+//                        result = Result.failure(e);
+//                    }
+//
+//                    xrayExitInteraction();
+//                    return result;
+//                });
+
+                val result = getInteractionService().callAnonymous(()->{
                     val currentInteraction = getInteractionService().currentInteraction();
                     xrayEnterInteraction(currentInteraction);
-                    val result = testRunner.run(testContext);
-                    xrayExitInteraction();
-                    return result;
+
+                    try {
+                        testRunner.run(testContext); // is allowed to throw
+                        return Result.success(true);
+                    } finally {
+                        xrayExitInteraction();
+                    }
+
                 });
 
-                getInteractionService().closeInteractionLayers();
+                traceLog.log("entering post test-runner phase");
 
                 assertFalse(getInteractionService().isInInteraction());
                 assert_no_initial_tx_context();
 
-                failWhenContextHasErrors(testContext);
-
-                if(isExpectedToRunSuccesful) {
-                    testContext.runVerify(onSuccess);
+                if(testContext.getExpectedException().isPresent()) {
+                    val expectedException = testContext.getExpectedException().get();
+                    val actualException = result.getFailure().map(Throwable::getClass).orElse(null);
+                    assertEquals(expectedException, actualException);
+                    testContext.runVerify(onFailure);
                     failWhenContextHasErrors(testContext);
+                    return;
+                }
+
+                if(result.isFailure()) {
+                    // unexpected failure
+                    fail("unexpeted exception during test: " + result.getFailure().get());
                 }
 
+                failWhenContextHasErrors(testContext);
+                testContext.runVerify(onSuccess);
+                failWhenContextHasErrors(testContext);
+
+
             } finally {
                 traceLog.log("5. exit test %s", displayName);
+                traceLog.footer();
             }
 
         });
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJdo.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJdo.java
index f49afde..a042cb6 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJdo.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJdo.java
@@ -32,14 +32,11 @@ import org.springframework.context.annotation.Import;
 import org.springframework.stereotype.Component;
 
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.fail;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
 import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.services.wrapper.DisabledException;
 import org.apache.isis.applib.services.wrapper.WrapperFactory;
 import org.apache.isis.applib.services.wrapper.control.SyncControl;
 import org.apache.isis.applib.services.xactn.TransactionService;
@@ -98,6 +95,11 @@ extends PublishingTestFactoryAbstract {
         switch(context.getScenario()) {
         case ENTITY_CREATION:
 
+            // given - nothing to do
+            break;
+
+        case ENTITY_PERSISTING:
+
             // given
             fixtureScripts.runPersona(JdoTestDomainPersona.PurgeAll);
             break;
@@ -110,13 +112,15 @@ extends PublishingTestFactoryAbstract {
             // given
             setupBookForJdo();
             break;
+        default:
+            throw _Exceptions.unmatchedCase(context.getScenario());
         }
     }
 
     // -- TESTS - PROGRAMMATIC
 
     @Override
-    protected boolean programmaticExecution(
+    protected void programmaticExecution(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -124,17 +128,25 @@ extends PublishingTestFactoryAbstract {
         // This test does not trigger command or execution publishing, however it does trigger
         // entity-change-publishing.
 
-
         switch(context.getScenario()) {
         case ENTITY_CREATION:
 
             context.runGiven();
+            //when
+            factoryService.detachedEntity(BookDto.sample().toJdoBook()); // should trigger an ObjectCreatedEvent
+            break;
+
+        case ENTITY_PERSISTING:
+
+            context.runGiven();
+            //when
             setupBookForJdo();
             break;
 
         case ENTITY_LOADING:
 
             context.runGiven();
+            //when
             withBookDo(book->{
                 assertNotNull(book);
             });
@@ -174,6 +186,7 @@ extends PublishingTestFactoryAbstract {
             withBookDo(book->{
 
                 context.runGiven();
+                //when
                 repository.removeAndFlush(book);
 
             });
@@ -183,13 +196,12 @@ extends PublishingTestFactoryAbstract {
             throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return true;
     }
 
     // -- TESTS - INTERACTION API
 
     @Override
-    protected boolean interactionApiExecution(
+    protected void interactionApiExecution(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -198,7 +210,6 @@ extends PublishingTestFactoryAbstract {
 
         case PROPERTY_UPDATE:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -221,7 +232,6 @@ extends PublishingTestFactoryAbstract {
             break;
         case ACTION_INVOCATION:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -244,13 +254,12 @@ extends PublishingTestFactoryAbstract {
             throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return true;
     }
 
     // -- TESTS - WRAPPER SYNC
 
     @Override
-    protected boolean wrapperSyncExecutionNoRules(
+    protected void wrapperSyncExecutionNoRules(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -259,7 +268,6 @@ extends PublishingTestFactoryAbstract {
 
         case PROPERTY_UPDATE:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -273,7 +281,6 @@ extends PublishingTestFactoryAbstract {
             break;
         case ACTION_INVOCATION:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -289,11 +296,10 @@ extends PublishingTestFactoryAbstract {
             throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return true;
     }
 
     @Override
-    protected boolean wrapperSyncExecutionWithFailure(
+    protected void wrapperSyncExecutionWithRules(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -302,7 +308,6 @@ extends PublishingTestFactoryAbstract {
 
         case PROPERTY_UPDATE:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -310,16 +315,15 @@ extends PublishingTestFactoryAbstract {
                 // when - running synchronous
                 val syncControl = SyncControl.control().withCheckRules(); // enforce rules
 
-                assertThrows(DisabledException.class, ()->{
+                //assertThrows(DisabledException.class, ()->{
                     wrapper.wrap(book, syncControl).setName("Book #2"); // should fail with DisabledException
-                });
+                //});
 
             });
 
             break;
         case ACTION_INVOCATION:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -327,9 +331,9 @@ extends PublishingTestFactoryAbstract {
                 // when - running synchronous
                 val syncControl = SyncControl.control().withCheckRules(); // enforce rules
 
-                assertThrows(DisabledException.class, ()->{
+                //assertThrows(DisabledException.class, ()->{
                     wrapper.wrap(book, syncControl).doubleThePrice(); // should fail with DisabledException
-                });
+                //});
 
             });
 
@@ -338,13 +342,12 @@ extends PublishingTestFactoryAbstract {
             throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return false;
     }
 
     // -- TESTS - WRAPPER ASYNC
 
     @Override
-    protected boolean wrapperAsyncExecutionNoRules(
+    protected void wrapperAsyncExecutionNoRules(
             final PublishingTestContext context) throws InterruptedException, ExecutionException, TimeoutException {
 
         context.bind(commitListener);
@@ -352,8 +355,6 @@ extends PublishingTestFactoryAbstract {
         // given
         val asyncControl = returningVoid().withSkipRules(); // don't enforce rules
 
-        // when
-
         withBookDo(book->{
 
             context.runGiven();
@@ -366,16 +367,14 @@ extends PublishingTestFactoryAbstract {
 
         asyncControl.getFuture().get(10, TimeUnit.SECONDS);
 
-        return true;
     }
 
     @Override
-    protected boolean wrapperAsyncExecutionWithFailure(
+    protected void wrapperAsyncExecutionWithRules(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
 
-        // when
         withBookDo(book->{
 
             context.runGiven();
@@ -383,16 +382,14 @@ extends PublishingTestFactoryAbstract {
             // when - running synchronous
             val asyncControl = returningVoid().withCheckRules(); // enforce rules
 
-            assertThrows(DisabledException.class, ()->{
+            //assertThrows(DisabledException.class, ()->{
                 // should fail with DisabledException (synchronous) within the calling Thread
                 wrapper.asyncWrap(book, asyncControl).setName("Book #2");
 
-                fail("unexpected code reach");
-            });
+            //});
 
         });
 
-        return false;
     }
 
     // -- TEST SETUP
@@ -408,8 +405,7 @@ extends PublishingTestFactoryAbstract {
 
         val products = new HashSet<JdoProduct>();
 
-        // should trigger an ObjectCreatedEvent
-        val detachedNewBook = factoryService.detachedEntity(BookDto.sample().toJdoBook());
+        val detachedNewBook = BookDto.sample().toJdoBook();
 
         products.add(detachedNewBook);
 
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJpa.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJpa.java
index 5bcd078..421a3f3 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJpa.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/publishing/PublishingTestFactoryJpa.java
@@ -29,14 +29,11 @@ import org.springframework.context.annotation.Import;
 import org.springframework.stereotype.Component;
 
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.fail;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
 import org.apache.isis.applib.services.repository.RepositoryService;
-import org.apache.isis.applib.services.wrapper.DisabledException;
 import org.apache.isis.applib.services.wrapper.WrapperFactory;
 import org.apache.isis.applib.services.wrapper.control.SyncControl;
 import org.apache.isis.applib.services.xactn.TransactionService;
@@ -94,6 +91,12 @@ extends PublishingTestFactoryAbstract {
         switch(context.getScenario()) {
         case ENTITY_CREATION:
 
+            // given - nothing to do
+            break;
+
+        case ENTITY_PERSISTING:
+
+
             // given
             fixtureScripts.runPersona(JpaTestDomainPersona.PurgeAll);
             break;
@@ -106,13 +109,15 @@ extends PublishingTestFactoryAbstract {
             // given
             setupBookForJpa();
             break;
+        default:
+            throw _Exceptions.unmatchedCase(context.getScenario());
         }
     }
 
     // -- TESTS - PROGRAMMATIC
 
     @Override
-    protected boolean programmaticExecution(
+    protected void programmaticExecution(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -124,17 +129,27 @@ extends PublishingTestFactoryAbstract {
         case ENTITY_CREATION:
 
             context.runGiven();
+            //when
+            factoryService.detachedEntity(BookDto.sample().toJdoBook()); // should trigger an ObjectCreatedEvent
+            break;
+
+        case ENTITY_PERSISTING:
+
+            context.runGiven();
+            //when
             setupBookForJpa();
             break;
 
         case ENTITY_LOADING:
 
             context.runGiven();
+            //when
             withBookDo(book->{
                 assertNotNull(book);
             });
             break;
 
+
         case PROPERTY_UPDATE:
 
             withBookDo(book->{
@@ -168,20 +183,22 @@ extends PublishingTestFactoryAbstract {
             withBookDo(book->{
 
                 context.runGiven();
+                //when
                 repository.removeAndFlush(book);
 
             });
 
             break;
+        default:
+            throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return true;
     }
 
     // -- TESTS - INTERACTION API
 
     @Override
-    protected boolean interactionApiExecution(
+    protected void interactionApiExecution(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -190,7 +207,6 @@ extends PublishingTestFactoryAbstract {
 
         case PROPERTY_UPDATE:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -213,7 +229,6 @@ extends PublishingTestFactoryAbstract {
             break;
         case ACTION_INVOCATION:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -236,13 +251,12 @@ extends PublishingTestFactoryAbstract {
             throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return true;
     }
 
     // -- TESTS - WRAPPER SYNC
 
     @Override
-    protected boolean wrapperSyncExecutionNoRules(
+    protected void wrapperSyncExecutionNoRules(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -251,7 +265,6 @@ extends PublishingTestFactoryAbstract {
 
         case PROPERTY_UPDATE:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -265,7 +278,6 @@ extends PublishingTestFactoryAbstract {
             break;
         case ACTION_INVOCATION:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -281,11 +293,10 @@ extends PublishingTestFactoryAbstract {
             throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return true;
     }
 
     @Override
-    protected boolean wrapperSyncExecutionWithFailure(
+    protected void wrapperSyncExecutionWithRules(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -294,7 +305,6 @@ extends PublishingTestFactoryAbstract {
 
         case PROPERTY_UPDATE:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -302,16 +312,15 @@ extends PublishingTestFactoryAbstract {
                 // when - running synchronous
                 val syncControl = SyncControl.control().withCheckRules(); // enforce rules
 
-                assertThrows(DisabledException.class, ()->{
-                    wrapper.wrap(book, syncControl).setName("Book #2"); // should fail with DisabledException
-                });
+                //assertThrows(DisabledException.class, ()->{
+                    wrapper.wrap(book, syncControl).setName("Book #2"); // should throw DisabledException
+                //});
 
             });
 
             break;
         case ACTION_INVOCATION:
 
-            // when
             withBookDo(book->{
 
                 context.runGiven();
@@ -319,9 +328,9 @@ extends PublishingTestFactoryAbstract {
                 // when - running synchronous
                 val syncControl = SyncControl.control().withCheckRules(); // enforce rules
 
-                assertThrows(DisabledException.class, ()->{
-                    wrapper.wrap(book, syncControl).doubleThePrice(); // should fail with DisabledException
-                });
+                //assertThrows(DisabledException.class, ()->{
+                    wrapper.wrap(book, syncControl).doubleThePrice(); // should throw DisabledException
+                //});
 
             });
 
@@ -330,13 +339,12 @@ extends PublishingTestFactoryAbstract {
             throw _Exceptions.unmatchedCase(context.getScenario());
         }
 
-        return false;
     }
 
     // -- TESTS - WRAPPER ASYNC
 
     @Override
-    protected boolean wrapperAsyncExecutionNoRules(
+    protected void wrapperAsyncExecutionNoRules(
             final PublishingTestContext context) throws InterruptedException, ExecutionException, TimeoutException {
 
         context.bind(commitListener);
@@ -358,11 +366,10 @@ extends PublishingTestFactoryAbstract {
 
         asyncControl.getFuture().get(10, TimeUnit.SECONDS);
 
-        return true;
     }
 
     @Override
-    protected boolean wrapperAsyncExecutionWithFailure(
+    protected void wrapperAsyncExecutionWithRules(
             final PublishingTestContext context) {
 
         context.bind(commitListener);
@@ -373,16 +380,14 @@ extends PublishingTestFactoryAbstract {
             // when - running synchronous
             val asyncControl = returningVoid().withCheckRules(); // enforce rules
 
-            assertThrows(DisabledException.class, ()->{
+            //assertThrows(DisabledException.class, ()->{
                 // should fail with DisabledException (synchronous) within the calling Thread
                 wrapper.asyncWrap(book, asyncControl).setName("Book #2");
 
-                fail("unexpected code reach");
-            });
+            //});
 
         });
 
-        return false;
     }
 
     // -- TEST SETUP
@@ -398,8 +403,7 @@ extends PublishingTestFactoryAbstract {
 
         val products = new HashSet<JpaProduct>();
 
-        // should trigger an ObjectCreatedEvent
-        val detachedNewBook = factoryService.detachedEntity(BookDto.sample().toJpaBook());
+        val detachedNewBook = BookDto.sample().toJpaBook();
 
         products.add(detachedNewBook);