So basically what I was trying to do was very similar to a password reset token with a limited time to live. So the Command "Request Reset" would create a token "(secret, expiry date)". Resulting in an event "reset requested (secret, expiry date)". And the aggregate calculated the expiry date by "Instant.now().plus(SOME DURATION)".
So I refactored this to generating an event "reset requested (secret, SOME DURATION)" and I injected the event timestamp into the command handlers (e.g., a matching saga) which then can calculate the expiry date locally.
For testing of the aggregate this eliminates the need for fixing the time ... for now.
I actually consider this a better design from the design of the events point of view.
There are however some drawbacks:
* For now I have not verified, if the test fixture actually keeps all timestamps constant with regards to the fixture creation time. At least the 2.4 docs say so.
* The fixture has no public method which allows me to access the time it has stored. So I cannot use it reliably in tests for checking timestamps.
There is one scenario which is not critical for my use-case, where I had to drop a small feature and related unit tests.
If a command reaches the aggregate after the timeout, it should refuse the command.
I have not found a way in the aggregate fixture to advance time. So this I cannot test this behaviour.
It wouldn't be necessary to actually provide the test fixture with similar methods as the saga fixture. In the aggregate case, it would be sufficient, if:
* I would know the timestamp used by the fixture for new events (see above)
* I could manually set the timestamp of the fixture.given(event) events. So I could put these into the past.
Following the idea of only using timestamp-relative event data, together with the last two points would probably eliminate most cases which require a fixed clock for testing.
The testing fixture timestamp handling improvements would be a small feature request from my side :-) Or maybe I have just not found out how to do it.
I would be interested in your opinions on this issue.
/**
* Inject arbitrary test/stub setup tasks into a stream of <code>givenCommands</code>.
* <p>Fixture configuration:
* <pre><code>
* fixture.registerCommandHandler(TestSetupCommand.class, TestSetupCommand.HANDLER)
* </code></pre>
* <p>
* Usage:
* <pre><code>
* fixture.givenCommands(
* command1,
* command2,
* TestSetupCommand.execute(() -> stub.configureValue("FOO")),
* command3
* )...
* </code></pre>
*/
public interface TestSetupCommand {
void run();
CommandHandler<TestSetupCommand> HANDLER = new CommandHandler<TestSetupCommand>() {
@Override
public Object handle(CommandMessage<TestSetupCommand> commandMessage, UnitOfWork unitOfWork) throws Throwable {
commandMessage.getPayload().run();
return Void.TYPE;
}
};
static CommandMessage<TestSetupCommand> execute(TestSetupCommand task) {
return new GenericCommandMessage<>(TestSetupCommand.class.getCanonicalName(), task, MetaData.emptyInstance());
}
}
September 17, 2016 at 3:25 PM
Thank you for your comments and examples. These are very reasonable approaches.Also I think the semantics of controlling the timestamps of the test fixture in the sense that you could say something like the follwoing would result in very readable tests. With the mock you have the testcase all over the place of your testclass.fixture.givenEventAt(event1,instant1).givenEventAt(event2,instant2).whenCommandAt(command,instant).expect......or:fixture.givenInstant(instant1).givenEvent(event1,event2).givenInstant(instant2).whenCommand(command)....(maybe this is easy to implement by extending the existing fixture)Here it is absolutely obvious what is happening. But it requires that you let go of accessing the current time directly in your aggrgate and you rely on the timestamp mechanism. I would also require Axon to be able to inject not only event timestamps with @Timestamp, but also command timestamps (because decsions on state change may depend on the time). I am not sure which implications enabling this would have.From my point of view the other options are starting to sound increasingly like hacks to get around the current limitations.Your approach ist aiming exactly at what I was describing and achives such a behaviour. Very cool. Still it would be nice to be able to do this out of the box with the fixture.Thanks.DominicAm Samstag, 17. September 2016 22:03:19 UTC+2 schrieb Patrick Haas:
--
You received this message because you are subscribed to the Google Groups "Axon Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to axonframewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
September 17, 2016 at 1:03 PM
--
You received this message because you are subscribed to the Google Groups "Axon Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to axonframewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
September 16, 2016 at 3:34 PM
So basically what I was trying to do was very similar to a password reset token with a limited time to live. So the Command "Request Reset" would create a token "(secret, expiry date)". Resulting in an event "reset requested (secret, expiry date)". And the aggregate calculated the expiry date by "Instant.now().plus(SOME DURATION)".
So I refactored this to generating an event "reset requested (secret, SOME DURATION)" and I injected the event timestamp into the command handlers (e.g., a matching saga) which then can calculate the expiry date locally.
For testing of the aggregate this eliminates the need for fixing the time ... for now.
I actually consider this a better design from the design of the events point of view.
There are however some drawbacks:
* For now I have not verified, if the test fixture actually keeps all timestamps constant with regards to the fixture creation time. At least the 2.4 docs say so.
* The fixture has no public method which allows me to access the time it has stored. So I cannot use it reliably in tests for checking timestamps.
There is one scenario which is not critical for my use-case, where I had to drop a small feature and related unit tests.
If a command reaches the aggregate after the timeout, it should refuse the command.
I have not found a way in the aggregate fixture to advance time. So this I cannot test this behaviour.
It wouldn't be necessary to actually provide the test fixture with similar methods as the saga fixture. In the aggregate case, it would be sufficient, if:
* I would know the timestamp used by the fixture for new events (see above)
* I could manually set the timestamp of the fixture.given(event) events. So I could put these into the past.
Following the idea of only using timestamp-relative event data, together with the last two points would probably eliminate most cases which require a fixed clock for testing.
The testing fixture timestamp handling improvements would be a small feature request from my side :-) Or maybe I have just not found out how to do it.
I would be interested in your opinions on this issue.
Best regards,Dominic
Am Freitag, 16. September 2016 23:44:10 UTC+2 schrieb Dominic Heutelbeck:
--
You received this message because you are subscribed to the Google Groups "Axon Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to axonframewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
September 16, 2016 at 2:44 PM
Hello,I am currently trying to migrate a small code base from Axon 2.4 to 3.0-M4.Orverall this is pretty smooth.Apparantly, the dependency on joda time is gone in favour for java.time.So previously you would use DateTimeUtils.setCurrentMillisFixed() in testing.Is there already a best practice for testing aggregates which emit time based events?Searching for the problem in general, I find, that it is recommended to add a Clock.fixed object to the dependencies of the object under test.How would I need to configure a spring application to inject a clock ? Also how does this relate to the lifecycle of the aggregate?For example, using a command handler constructor, the injected Clock is not yet available in the constructor.Currently this appears to create quite some overhead compared to the simplicity of the setCurrentMillisFixed approach.Does anybody have expreiences, best practices, code samples ?The axon bank example on github currently avoids time issues.Thanks for your help.Best regards,Dominic
--
You received this message because you are subscribed to the Google Groups "Axon Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to axonframewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.