Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created stub implementation of AggregateLifecycle that can be used in…
… tests Especially in unit tests of aggregates that do not use event sourcing. When they call apply(), and exception is thrown indicating that no lifecycle has been registered. The StubAggregateLifecycle can be used to register a lifecycle that just keeps track of applied events. In JUnit tests, the StubAggregateLifecycleRule can be used to automatically start these lifecycles during tests. Resolves #336
- Loading branch information
Showing
6 changed files
with
334 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
test/src/main/java/org/axonframework/test/aggregate/StubAggregateLifecycle.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* Copyright (c) 2010-2017. Axon Framework | ||
* | ||
* Licensed 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.axonframework.test.aggregate; | ||
|
||
import org.axonframework.commandhandling.model.AggregateLifecycle; | ||
import org.axonframework.commandhandling.model.ApplyMore; | ||
import org.axonframework.eventhandling.EventMessage; | ||
import org.axonframework.eventhandling.GenericEventMessage; | ||
import org.axonframework.messaging.MetaData; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.CopyOnWriteArrayList; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* Stub implementation of an AggregateLifecycle that registers all applied events for verification later. This | ||
* lifecycle instance can be activated (see {@link #activate()}) and deactivated (see {@link #close()}) at will. Events | ||
* applied while it is active are stored and can be retrieved using {@link #getAppliedEvents()} or | ||
* {@link #getAppliedEventPayloads()}. | ||
* <p> | ||
* When using with JUnit, consider using the {@link StubAggregateLifecycleRule} with {@link org.junit.Rule @Rule} instead, | ||
* as it is easier and safer to use. | ||
*/ | ||
public class StubAggregateLifecycle extends AggregateLifecycle { | ||
|
||
private Runnable registration; | ||
private List<EventMessage<?>> appliedMessages = new CopyOnWriteArrayList<>(); | ||
private boolean deleted; | ||
|
||
/** | ||
* Activates this lifecycle instance. Any invocations to static AggregateLifecycle methods will use this instance | ||
* until {@link #close()} is called. | ||
*/ | ||
public void activate() { | ||
this.registration = registerAsCurrent(); | ||
} | ||
|
||
/** | ||
* Closes this lifecycle instance, restoring to the situation prior to this lifecycle being started. If any | ||
* lifecycle instance was active before this one started, it will be reactivated. | ||
*/ | ||
public void close() { | ||
if (registration != null) { | ||
registration.run(); | ||
} | ||
registration = null; | ||
} | ||
|
||
@Override | ||
protected boolean getIsLive() { | ||
return true; | ||
} | ||
|
||
@Override | ||
protected void doMarkDeleted() { | ||
this.deleted = true; | ||
} | ||
|
||
@Override | ||
protected <T> ApplyMore doApply(T payload, MetaData metaData) { | ||
appliedMessages.add(new GenericEventMessage<>(payload, metaData)); | ||
|
||
return new ApplyMore() { | ||
@Override | ||
public ApplyMore andThenApply(Supplier<?> payloadOrMessageSupplier) { | ||
appliedMessages.add(GenericEventMessage.asEventMessage(payloadOrMessageSupplier.get())); | ||
return this; | ||
} | ||
|
||
@Override | ||
public ApplyMore andThen(Runnable runnable) { | ||
runnable.run(); | ||
return this; | ||
} | ||
}; | ||
} | ||
|
||
/** | ||
* Returns the list of applied Events for this lifecycle instance. | ||
* <p> | ||
* Note that this list is not reset when activating or deactivating the lifecycle. | ||
* | ||
* @return the list of messages applied while this lifecycle instance was active | ||
*/ | ||
public List<EventMessage<?>> getAppliedEvents() { | ||
return appliedMessages; | ||
} | ||
|
||
/** | ||
* Returns the payloads of the Events applied while this lifecycle instance was active. This is usually the | ||
* parameter passed to the {@link AggregateLifecycle#apply(Object)} method. | ||
* | ||
* @return the payloads of the applied events. | ||
*/ | ||
public List<Object> getAppliedEventPayloads() { | ||
return appliedMessages.stream().map(EventMessage::getPayload).collect(Collectors.toList()); | ||
} | ||
|
||
/** | ||
* Indicates whether an Aggregate has invoked "markDeleted" while this lifecycle was active. | ||
* | ||
* @return {@code true} if {@link #markDeleted()} was invoked, otherwise {@code false} | ||
*/ | ||
public boolean isMarkedDeleted() { | ||
return deleted; | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
test/src/main/java/org/axonframework/test/aggregate/StubAggregateLifecycleRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright (c) 2010-2017. Axon Framework | ||
* | ||
* Licensed 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.axonframework.test.aggregate; | ||
|
||
import org.junit.rules.TestRule; | ||
import org.junit.runner.Description; | ||
import org.junit.runners.model.Statement; | ||
|
||
/** | ||
* Implementation of StubAggregateLifecycle that can be used as an {@link org.junit.Rule} annotated method or field | ||
* in a test class. In that case, the JUnit lifecycle will automatically register and unregister the | ||
* StubAggregateLifecycle. | ||
* | ||
* Usage example: | ||
* <pre> | ||
* @Rule | ||
* public StubAggregateLifecycleRule lifecycle = new StubAggregateLifecycleRule(); | ||
* | ||
* @Test | ||
* public void testMethod() { | ||
* ... perform tests ... | ||
* | ||
* // get applied events from lifecycle to validate some more | ||
* lifecycle.getAppliedEvents(); | ||
* } | ||
* </pre> | ||
*/ | ||
public class StubAggregateLifecycleRule extends StubAggregateLifecycle implements TestRule { | ||
|
||
@Override | ||
public Statement apply(Statement base, Description description) { | ||
return new Statement() { | ||
@Override | ||
public void evaluate() throws Throwable { | ||
activate(); | ||
try { | ||
base.evaluate(); | ||
} finally { | ||
close(); | ||
} | ||
} | ||
}; | ||
} | ||
|
||
} |
49 changes: 49 additions & 0 deletions
49
test/src/test/java/org/axonframework/test/aggregate/StubAggregateLifecycleRuleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Copyright (c) 2010-2017. Axon Framework | ||
* | ||
* Licensed 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.axonframework.test.aggregate; | ||
|
||
import org.junit.Rule; | ||
import org.junit.Test; | ||
|
||
import static org.axonframework.commandhandling.model.AggregateLifecycle.apply; | ||
import static org.axonframework.commandhandling.model.AggregateLifecycle.markDeleted; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
public class StubAggregateLifecycleRuleTest { | ||
|
||
@Rule | ||
public StubAggregateLifecycleRule testSubject = new StubAggregateLifecycleRule(); | ||
|
||
@Test | ||
public void testAppliedEventsArePassedToActiveLifecycle() throws Exception { | ||
apply("test"); | ||
|
||
assertEquals(1, testSubject.getAppliedEvents().size()); | ||
assertEquals("test", testSubject.getAppliedEventPayloads().get(0)); | ||
assertEquals("test", testSubject.getAppliedEvents().get(0).getPayload()); | ||
} | ||
|
||
@Test | ||
public void testMarkDeletedIsRegisteredWithActiveLifecycle() throws Exception { | ||
markDeleted(); | ||
|
||
assertEquals(0, testSubject.getAppliedEvents().size()); | ||
assertTrue(testSubject.isMarkedDeleted()); | ||
} | ||
|
||
} |
71 changes: 71 additions & 0 deletions
71
test/src/test/java/org/axonframework/test/aggregate/StubAggregateLifecycleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright (c) 2010-2017. Axon Framework | ||
* | ||
* Licensed 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.axonframework.test.aggregate; | ||
|
||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import static org.axonframework.commandhandling.model.AggregateLifecycle.apply; | ||
import static org.axonframework.commandhandling.model.AggregateLifecycle.markDeleted; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
public class StubAggregateLifecycleTest { | ||
private StubAggregateLifecycle testSubject; | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
testSubject = new StubAggregateLifecycle(); | ||
} | ||
|
||
@After | ||
public void tearDown() throws Exception { | ||
testSubject.close(); | ||
} | ||
|
||
@Test(expected = IllegalStateException.class) | ||
public void testLifecycleIsNotRegisteredAutomatically() throws Exception { | ||
apply("test"); | ||
} | ||
|
||
@Test(expected = IllegalStateException.class) | ||
public void testApplyingEventsAfterDeactivationFails() throws Exception { | ||
testSubject.activate(); | ||
testSubject.close(); | ||
apply("test"); | ||
} | ||
|
||
@Test | ||
public void testAppliedEventsArePassedToActiveLifecycle() throws Exception { | ||
testSubject.activate(); | ||
apply("test"); | ||
|
||
assertEquals(1, testSubject.getAppliedEvents().size()); | ||
assertEquals("test", testSubject.getAppliedEventPayloads().get(0)); | ||
assertEquals("test", testSubject.getAppliedEvents().get(0).getPayload()); | ||
} | ||
|
||
@Test | ||
public void testMarkDeletedIsRegisteredWithActiveLifecycle() throws Exception { | ||
testSubject.activate(); | ||
markDeleted(); | ||
|
||
assertEquals(0, testSubject.getAppliedEvents().size()); | ||
assertTrue(testSubject.isMarkedDeleted()); | ||
} | ||
} |