You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/07/12 18:13:10 UTC
[1/2] git commit: ISIS-463: IntegrationTestAbstract pick
ScenarioExecution...
Updated Branches:
refs/heads/master 593f500bc -> 68136cc7c
ISIS-463: IntegrationTestAbstract pick ScenarioExecution...
... from the ThreadLocal, rather than store as a (static) field.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/5760f554
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/5760f554
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/5760f554
Branch: refs/heads/master
Commit: 5760f554700b0d8baf367f22a1ef81f59443e413
Parents: 593f500
Author: Dan Haywood <da...@apache.org>
Authored: Fri Jul 12 14:23:36 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Jul 12 14:23:36 2013 +0100
----------------------------------------------------------------------
.../isis/core/integtestsupport/IntegrationTestAbstract.java | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/5760f554/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IntegrationTestAbstract.java
----------------------------------------------------------------------
diff --git a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IntegrationTestAbstract.java b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IntegrationTestAbstract.java
index e4f9d55..938dd17 100644
--- a/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IntegrationTestAbstract.java
+++ b/core/integtestsupport/src/main/java/org/apache/isis/core/integtestsupport/IntegrationTestAbstract.java
@@ -42,7 +42,9 @@ import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
*/
public abstract class IntegrationTestAbstract {
- protected static ScenarioExecution scenarioExecution;
+ protected static ScenarioExecution scenarioExecution() {
+ return ScenarioExecution.current();
+ }
// //////////////////////////////////////
@@ -104,9 +106,6 @@ public abstract class IntegrationTestAbstract {
}
- private ScenarioExecution scenarioExecution() {
- return scenarioExecution;
- }
// //////////////////////////////////////
[2/2] git commit: ISIS-463: refactoring to allow specs to run under
unit scope (with mocks)
Posted by da...@apache.org.
ISIS-463: refactoring to allow specs to run under unit scope (with mocks)
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/68136cc7
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/68136cc7
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/68136cc7
Branch: refs/heads/master
Commit: 68136cc7c188a8bb9e7dceecf07cf46fb0c9e3dd
Parents: 5760f55
Author: Dan Haywood <da...@apache.org>
Authored: Fri Jul 12 17:07:58 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Jul 12 17:07:58 2013 +0100
----------------------------------------------------------------------
core/specsupport/pom.xml | 8 +
.../core/specsupport/scenarios/InMemoryDB.java | 174 +++++++++++++++++++
.../scenarios/ScenarioExecution.java | 89 +++++++++-
.../scenarios/ScenarioExecutionForUnit.java | 131 ++++++++++++++
.../scenarios/ScenarioExecutionScope.java | 13 +-
.../specsupport/specs/CukeStepDefsAbstract.java | 51 +++++-
6 files changed, 455 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/68136cc7/core/specsupport/pom.xml
----------------------------------------------------------------------
diff --git a/core/specsupport/pom.xml b/core/specsupport/pom.xml
index ea1a304..99a19da 100644
--- a/core/specsupport/pom.xml
+++ b/core/specsupport/pom.xml
@@ -70,6 +70,14 @@
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.jmock</groupId>
+ <artifactId>jmock</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jmock</groupId>
+ <artifactId>jmock-legacy</artifactId>
+ </dependency>
<dependency>
<groupId>info.cukes</groupId>
http://git-wip-us.apache.org/repos/asf/isis/blob/68136cc7/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/InMemoryDB.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/InMemoryDB.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/InMemoryDB.java
new file mode 100644
index 0000000..ded1d9c
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/InMemoryDB.java
@@ -0,0 +1,174 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.scenarios;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+import org.hamcrest.Description;
+import org.jmock.api.Action;
+import org.jmock.api.Invocation;
+
+import org.apache.isis.applib.DomainObjectContainer;
+
+/**
+ * To support unit-scope specifications, intended to work with mocks.
+ *
+ * <p>
+ * The {@link #findByXxx(Class, Strategy)} provides an implementation of a JMock
+ * {@link Action} that can simulate searching for an object from a database, and
+ * optionally automatically creating a new one if {@link Strategy specified}.
+ *
+ * <p>
+ * If objects are created, then (mock) services are automatically injected. This is performed by
+ * searching for <tt>injectXxx()</tt> methods. The (mock) {@link DomainObjectContainer container}
+ * is also automatically injected, through the <tt>setXxx</tt> method.
+ *
+ * <p>
+ * Finally, note that the {@link #init(Object, String) init} hook method allows subclasses to
+ * customize the state of any objects created.
+ */
+public class InMemoryDB {
+
+ private final ScenarioExecution scenarioExecution;
+
+ public InMemoryDB(ScenarioExecution scenarioExecution) {
+ this.scenarioExecution = scenarioExecution;
+ }
+
+ public static class EntityId {
+ private final String type;
+ private final String id;
+ public EntityId(Class<?> type, String id) {
+ this.type = type.getName();
+ this.id = id;
+ }
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ InMemoryDB.EntityId other = (InMemoryDB.EntityId) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (type == null) {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ return true;
+ }
+ @Override
+ public String toString() {
+ return "EntityId [type=" + type + ", id=" + id + "]";
+ }
+ }
+
+ private Map<InMemoryDB.EntityId, Object> objectsById = Maps.newHashMap();
+
+ private Object get(Class<?> cls, final String id) {
+ while(cls != null) {
+ // search for this class and all superclasses
+ final InMemoryDB.EntityId entityId = new EntityId(cls, id);
+ final Object object = objectsById.get(entityId);
+ if(object != null) {
+ return object;
+ }
+ cls = cls.getSuperclass();
+ }
+ return null;
+ }
+
+ private Object getElseCreate(Class<?> cls, final String id) {
+ final Object object = get(cls, id);
+ if(object != null) {
+ return object;
+ }
+ Object obj;
+ obj = instantiateAndInject(cls);
+ init(obj, id);
+
+ // put for this class and all superclasses
+ while(cls != null) {
+ final InMemoryDB.EntityId entityId = new EntityId(cls, id);
+ objectsById.put(entityId, obj);
+ cls = cls.getSuperclass();
+ }
+ return obj;
+ }
+
+ private Object instantiateAndInject(Class<?> cls) {
+ try {
+ return scenarioExecution.injectServices(cls.newInstance());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public enum Strategy {
+ STRICT,
+ AUTOCREATE
+ }
+
+ public Action findByXxx(final Class<?> cls, final InMemoryDB.Strategy strategy) {
+ return new Action() {
+
+ @Override
+ public Object invoke(Invocation invocation) throws Throwable {
+ if(invocation.getParameterCount() != 1) {
+ throw new IllegalArgumentException("intended for action of findByXxx");
+ }
+ final Object argObj = invocation.getParameter(0);
+ if(!(argObj instanceof String)) {
+ throw new IllegalArgumentException("Argument must be a string");
+ }
+ String arg = (String) argObj;
+ if(strategy == Strategy.AUTOCREATE) {
+ return getElseCreate(cls, arg);
+ } else {
+ return get(cls, arg);
+ }
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("findByXxx for " + cls.getName());
+ }
+ };
+ }
+
+ /**
+ * Hook to initialize if possible.
+ */
+ protected void init(Object obj, String id) {
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/68136cc7/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java
index 04cc378..741d54a 100644
--- a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecution.java
@@ -16,10 +16,15 @@
*/
package org.apache.isis.core.specsupport.scenarios;
+import java.lang.reflect.Method;
import java.util.Map;
import com.google.common.collect.Maps;
+import org.jmock.Sequence;
+import org.jmock.States;
+import org.jmock.internal.ExpectationBuilder;
+
import org.apache.isis.applib.DomainObjectContainer;
import org.apache.isis.applib.fixtures.InstallableFixture;
import org.apache.isis.applib.services.wrapper.WrapperFactory;
@@ -50,7 +55,7 @@ import org.apache.isis.applib.services.wrapper.WrapperFactory;
* <tt>IntegrationScenarioExecution</tt> provides additional support for fixtures and
* transaction management, used both by integration-scoped specs and by integration tests.
*/
-public class ScenarioExecution {
+public abstract class ScenarioExecution {
private static ThreadLocal<ScenarioExecution> current = new ThreadLocal<ScenarioExecution>();
@@ -67,7 +72,7 @@ public class ScenarioExecution {
protected final DomainServiceProvider dsp;
- public ScenarioExecution(final DomainServiceProvider dsp) {
+ protected ScenarioExecution(final DomainServiceProvider dsp) {
this.dsp = dsp;
current.set(this);
}
@@ -247,11 +252,59 @@ public class ScenarioExecution {
// //////////////////////////////////////
/**
+ * Install expectations on mock domain services.
+ *
+ * <p>
+ * This implementation is a no-op, but subclasses of this class tailored to
+ * supporting unit specs/tests are expected to override.
+ */
+ public void checking(ExpectationBuilder expectations) {
+ // do nothing
+ }
+
+ /**
+ * Install expectations on mock domain services.
+ *
+ * <p>
+ * This implementation is a no-op, but subclasses of this class tailored to
+ * supporting unit specs/tests are expected to override.
+ */
+ public void assertIsSatisfied() {
+ // do nothing
+ }
+
+ /**
+ * Define {@link Sequence} in a (JMock) interaction.
+ *
+ * <p>
+ * This implementation is a no-op, but subclasses of this class tailored to
+ * supporting unit specs/tests are expected to override.
+ */
+ public Sequence sequence(String name) {
+ // do nothing
+ return null;
+ }
+
+ /**
+ * Define {@link States} in a (JMock) interaction.
+ *
+ * <p>
+ * This implementation is a no-op, but subclasses of this class tailored to
+ * supporting unit specs/tests are expected to override.
+ */
+ public States states(String name) {
+ // do nothing
+ return null;
+ }
+
+ // //////////////////////////////////////
+
+ /**
* Install arbitrary fixtures, eg before an integration tests or as part of a
* Cucumber step definitions or hook.
*
* <p>
- * This implementation has a no-op, but subclasses of this class tailored to
+ * This implementation is a no-op, but subclasses of this class tailored to
* supporting integration specs/tests are expected to override.
*/
public void install(InstallableFixture... fixtures) {
@@ -264,7 +317,7 @@ public class ScenarioExecution {
* For Cucumber hooks to call, performing transaction management around each step.
*
* <p>
- * This implementation has a no-op, but subclasses of this class tailored to
+ * This implementation is a no-op, but subclasses of this class tailored to
* supporting integration specs are expected to override. (Integration tests can use
* the <tt>IsisTransactionRule</tt> to do transaction management transparently).
*/
@@ -276,7 +329,7 @@ public class ScenarioExecution {
* For Cucumber hooks to call, performing transaction management around each step.
*
* <p>
- * This implementation has a no-op, but subclasses of this class tailored to
+ * This implementation is a no-op, but subclasses of this class tailored to
* supporting integration specs are expected to override. (Integration tests can use
* the <tt>IsisTransactionRule</tt> to do transaction management transparently).
*/
@@ -284,4 +337,30 @@ public class ScenarioExecution {
// do nothing
}
+ // //////////////////////////////////////
+
+ public Object injectServices(final Object obj) {
+ try {
+ final Method[] methods = obj.getClass().getMethods();
+ for (Method method : methods) {
+ final Class<?>[] parameterTypes = method.getParameterTypes();
+ if(parameterTypes.length != 1) {
+ continue;
+ }
+ final Class<?> serviceClass = parameterTypes[0];
+ if(method.getName().startsWith("inject")) {
+ final Object service = service(serviceClass);
+ method.invoke(obj, service);
+ }
+ if(method.getName().startsWith("set") && serviceClass == DomainObjectContainer.class) {
+ final Object container = container();
+ method.invoke(obj, container);
+ }
+ }
+ return obj;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/68136cc7/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionForUnit.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionForUnit.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionForUnit.java
new file mode 100644
index 0000000..c8e0531
--- /dev/null
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionForUnit.java
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.core.specsupport.scenarios;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+import org.hamcrest.Description;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.Sequence;
+import org.jmock.States;
+import org.jmock.api.Action;
+import org.jmock.api.Invocation;
+import org.jmock.internal.ExpectationBuilder;
+import org.jmock.lib.legacy.ClassImposteriser;
+
+import org.apache.isis.applib.DomainObjectContainer;
+
+/**
+ * An implementation of {@link ScenarioExecution} with which uses JMock to provide
+ * all services.
+ *
+ * <p>
+ * Expectations can be {@link Mockery#checking(org.jmock.internal.ExpectationBuilder) set}
+ * and interactions {@link Mockery#assertIsSatisfied() verified} by
+ * {@link #mockery() accessing} the underlying {@link Mockery}.
+ */
+public class ScenarioExecutionForUnit extends ScenarioExecution {
+
+ private static class DomainServiceProviderMockery implements DomainServiceProvider {
+
+ private DomainObjectContainer mockContainer = null;
+ private final Map<Class<?>, Object> mocks = Maps.newHashMap();
+
+ private final Mockery context = new Mockery() {{
+ setImposteriser(ClassImposteriser.INSTANCE);
+ }};
+ private ScenarioExecution scenarioExecution;
+
+ @Override
+ public DomainObjectContainer getContainer() {
+ if(mockContainer == null) {
+ mockContainer = getService(DomainObjectContainer.class);
+ context.checking(new Expectations() {
+ {
+ allowing(mockContainer).newTransientInstance(with(Expectations.<Class<?>>anything()));
+ will(new Action() {
+
+ @SuppressWarnings("rawtypes")
+ public Object invoke(Invocation invocation) throws Throwable {
+ Class cls = (Class) invocation.getParameter(0);
+ return scenarioExecution.injectServices(cls.newInstance());
+ }
+
+ public void describeTo(Description description) {
+ description.appendText("newTransientInstance");
+ }
+ });
+
+ allowing(mockContainer).persistIfNotAlready(with(anything()));
+ }
+ });
+ }
+ return mockContainer;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ Object mock = mocks.get(serviceClass);
+ if(mock == null) {
+ mock = context.mock(serviceClass);
+ }
+ mocks.put(serviceClass, mock);
+ return (T) mock;
+ }
+
+ public Mockery mockery() {
+ return context;
+ }
+
+ private DomainServiceProviderMockery init(ScenarioExecution scenarioExecution) {
+ this.scenarioExecution = scenarioExecution;
+ return this;
+ }
+ }
+
+ private final ScenarioExecutionForUnit.DomainServiceProviderMockery dspm;
+
+ public ScenarioExecutionForUnit() {
+ this(new DomainServiceProviderMockery());
+ }
+ private ScenarioExecutionForUnit(ScenarioExecutionForUnit.DomainServiceProviderMockery dspm) {
+ super(dspm);
+ this.dspm = dspm.init(this);
+ }
+
+ // //////////////////////////////////////
+
+ public void checking(ExpectationBuilder expectations) {
+ dspm.mockery().checking(expectations);
+ }
+
+ public void assertIsSatisfied() {
+ dspm.mockery().assertIsSatisfied();
+ }
+
+ public Sequence sequence(String name) {
+ return dspm.mockery().sequence(name);
+ }
+ public States states(String name) {
+ return dspm.mockery().states(name);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/68136cc7/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java
index 3c8f487..a6a89db 100644
--- a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/scenarios/ScenarioExecutionScope.java
@@ -23,7 +23,8 @@ package org.apache.isis.core.specsupport.scenarios;
*/
public class ScenarioExecutionScope {
- public final static ScenarioExecutionScope UNIT = new ScenarioExecutionScope(ScenarioExecution.class);
+ public final static ScenarioExecutionScope UNIT = new ScenarioExecutionScope(ScenarioExecutionForUnit.class);
+ public final static ScenarioExecutionScope INTEGRATION = new ScenarioExecutionScope("org.apache.isis.core.integtestsupport.scenarios.ScenarioExecutionForIntegration");
private final Class<? extends ScenarioExecution> scenarioExecutionClass;
@@ -31,6 +32,16 @@ public class ScenarioExecutionScope {
this.scenarioExecutionClass = scenarioExecutionClass;
}
+ @SuppressWarnings("unchecked")
+ public ScenarioExecutionScope(String scenarioExecutionClassName) {
+ try {
+ this.scenarioExecutionClass = (Class<? extends ScenarioExecution>)
+ Thread.currentThread().getContextClassLoader().loadClass(scenarioExecutionClassName);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
public ScenarioExecution instantiate() {
try {
return scenarioExecutionClass.newInstance();
http://git-wip-us.apache.org/repos/asf/isis/blob/68136cc7/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java
----------------------------------------------------------------------
diff --git a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java
index 190a39e..2e497ac 100644
--- a/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java
+++ b/core/specsupport/src/main/java/org/apache/isis/core/specsupport/specs/CukeStepDefsAbstract.java
@@ -25,6 +25,9 @@ import java.util.List;
import com.google.common.collect.Lists;
+import org.jmock.Sequence;
+import org.jmock.States;
+import org.jmock.internal.ExpectationBuilder;
import org.junit.Assert;
import cucumber.api.java.Before;
@@ -32,6 +35,7 @@ import cucumber.api.java.Before;
import org.apache.isis.applib.DomainObjectContainer;
import org.apache.isis.applib.services.wrapper.WrapperFactory;
import org.apache.isis.core.specsupport.scenarios.ScenarioExecution;
+import org.apache.isis.core.specsupport.scenarios.ScenarioExecutionForUnit;
import org.apache.isis.core.specsupport.scenarios.ScenarioExecutionScope;
@@ -66,6 +70,7 @@ public abstract class CukeStepDefsAbstract {
*/
public void put(String type, String id, Object value) {
scenarioExecution().put(type, id, value);
+
}
/**
@@ -107,16 +112,44 @@ public abstract class CukeStepDefsAbstract {
* Convenience method
*/
protected <T> T wrap(T obj) {
- return scenarioExecution.wrapperFactory().wrap(obj);
+ return wrapperFactory().wrap(obj);
}
/**
* Convenience method
*/
protected <T> T unwrap(T obj) {
- return scenarioExecution.wrapperFactory().unwrap(obj);
+ return wrapperFactory().unwrap(obj);
+ }
+
+ /**
+ * Convenience method
+ */
+ public void checking(ExpectationBuilder expectations) {
+ scenarioExecution().checking(expectations);
}
+ /**
+ * Convenience method
+ */
+ public void assertIsSatisfied() {
+ scenarioExecution().assertIsSatisfied();
+ }
+
+ /**
+ * Convenience method
+ */
+ public Sequence sequence(String name) {
+ return scenarioExecution().sequence(name);
+ }
+
+ /**
+ * Convenience method
+ */
+ public States states(String name) {
+ return scenarioExecution().states(name);
+ }
+
// //////////////////////////////////////
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -222,9 +255,17 @@ public abstract class CukeStepDefsAbstract {
* before(ScenarioExecutionScope.INTEGRATION);
* }
* </pre>
- * where <tt>ScenarioExecutionForMyAppIntegration</tt> is an application-specific subclass of
- * {@link ScenarioExecution} for integration-testing. Typically this is done using the
- * <tt>IsisSystemForTest</tt> class provided in the <tt>isis-core-integtestsupport</tt> module).
+ * The built-in {@link ScenarioExecutionScope#UNIT unit}-level scope will instantiate a
+ * {@link ScenarioExecutionForUnit}, while the built-in
+ * {@link ScenarioExecutionScope#INTEGRATION integration}-level scope instantiates
+ * <tt>ScenarioExecutionForIntegration</tt> (from the <tt>isis-core-integtestsupport</tt> module).
+ * The former provides access to domain services as mocks, whereas the latter wraps a running
+ * <tt>IsisSystemForTest</tt>.
+ *
+ * <p>
+ * If need be, it is also possible to define custom scopes, with a different implementation of
+ * {@link ScenarioExecution}. This might be done when unit testing where a large number of specs
+ * have similar expectations needing to be set on the mock domain services.
*
* <p>
* Not every class holding step definitions should have these hooks, only those that correspond to the logical