diff --git a/.gitignore b/.gitignore index 7451ff2..2e91def 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,34 @@ -# Ignore binary -gcqrs +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so -example/example +# Folders +_obj +_test -*.test +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe + +# User specific IDEA files +.idea/workspace.xml +.idea/tasks.xml + +# Sublime files +*.sublime-project +*.sublime-workspace +rethinkdb_data/fc1c4823-5b08-427f-96d8-8005cb47d1a5 + +# RethinkDB +rethinkdb_data diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..dfd5de1 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +go-cqrs \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..217af47 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..3572571 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.idea/dictionaries/dominik.xml b/.idea/dictionaries/dominik.xml new file mode 100644 index 0000000..f33c82c --- /dev/null +++ b/.idea/dictionaries/dominik.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..e206d70 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..c66df00 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..3b31283 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0254571 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,23 @@ + + + + + + + + + + Go SDK go1.2 darwin/amd64 + + + + + + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ecc6bb8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..922003b --- /dev/null +++ b/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..3b00020 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..275077f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/README.md b/README.md index d6fc57a..d4dc491 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ func (user *User) HandleUsernameChanged(e events.UsernameChanged) { } ``` -See the [User.go](https://github.com/pjvds/go-cqrs/blob/master/tests/domain/User.go) +See the [User.go](https://github.com/dominikmayer/go-cqrs/blob/master/tests/domain/User.go) source to see all the details. diff --git a/go-cqrs.iml b/go-cqrs.iml new file mode 100644 index 0000000..44ac922 --- /dev/null +++ b/go-cqrs.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/goconvey.sh b/goconvey.sh new file mode 100755 index 0000000..13831fb --- /dev/null +++ b/goconvey.sh @@ -0,0 +1,10 @@ +#!/bin/sh +if [ "$1" = "stop" ] +then + echo "Stopping GoConvey" + killall goconvey +else + echo "Starting GoConvey" + $GOPATH/bin/goconvey & + open http://localhost:8080 +fi diff --git a/sourcing/EventRecorder_test.go b/sourcing/EventRecorder_test.go index 8895610..d9ccafa 100644 --- a/sourcing/EventRecorder_test.go +++ b/sourcing/EventRecorder_test.go @@ -1,73 +1,56 @@ package sourcing import ( - . "launchpad.net/gocheck" + . "github.com/smartystreets/goconvey/convey" + "testing" ) -// The state for the test suite -type EventRecorderTestSuite struct { -} - -// Setup the test suite -var _ = Suite(&EventRecorderTestSuite{}) +func TestEventRecorder(t *testing.T) { + Convey("Given an event and a recorder", t, func() { + event := Event(struct { + Foo string + }{ + Foo: "bar", + }) + + recorder := NewEventRecorder() + + Convey("When we record the event", func() { + recorder.Record(&event) + + Convey("Then the recorder should have one event recorded", func() { + So(len(recorder.GetEvents()), ShouldEqual, 1) + + Convey("And the event should resemble the original one", func() { + recordedEvents := recorder.GetEvents() + So(recordedEvents[0], ShouldResemble, &event) // TODO: Why is it a pointer?? + }) + }) + }) + Convey("When we record the event again", func() { + recorder.Record(&event) + + Convey("Then the recorder should have two events recorded", func() { + So(len(recorder.GetEvents()), ShouldEqual, 2) + + Convey("And the second event should also resemble the original one", func() { + recordedEvents := recorder.GetEvents() + So(recordedEvents[1], ShouldResemble, &event) + }) + }) + Convey("When we clear the recorder", func() { + recorder.Clear() + + Convey("Then the recorder should have no more events recorded", func() { + So(len(recorder.GetEvents()), ShouldEqual, 0) + + Convey("And the recorder should be able to record the event again", func() { + recorder.Record(&event) + So(len(recorder.GetEvents()), ShouldEqual, 1) + }) + }) + }) + }) -// Make sure we can record events -func (s *EventRecorderTestSuite) TestRecord(c *C) { - event := Event(struct { - Foo string - }{ - Foo: "bar", }) - - recoder := NewEventRecorder() - recoder.Record(&event) - - c.Assert(recoder.GetEvents(), HasLen, 1) -} - -// Make sure we can record events, even if they are the same -func (s *EventRecorderTestSuite) TestRecordSameEventTwice(c *C) { - event := Event(struct { - Foo string - }{ - Foo: "bar", - }) - - recoder := NewEventRecorder() - recoder.Record(&event) - recoder.Record(&event) - - c.Assert(recoder.GetEvents(), HasLen, 2) -} - -func (s *EventRecorderTestSuite) TestClearClears(c *C) { - event := Event(struct { - Foo string - }{ - Foo: "bar", - }) - - recoder := NewEventRecorder() - recoder.Record(&event) - - c.Assert(recoder.GetEvents(), HasLen, 1) - - recoder.Clear() - - c.Assert(recoder.GetEvents(), HasLen, 0) -} - -func (s *EventRecorderTestSuite) TestCanRecordAfterClear(c *C) { - event := Event(struct { - Foo string - }{ - Foo: "bar", - }) - - recoder := NewEventRecorder() - recoder.Record(&event) - recoder.Clear() - recoder.Record(&event) - - c.Assert(recoder.GetEvents(), HasLen, 1) } diff --git a/sourcing/EventSourceId_test.go b/sourcing/EventSourceId_test.go index 512e10e..5847abd 100644 --- a/sourcing/EventSourceId_test.go +++ b/sourcing/EventSourceId_test.go @@ -2,46 +2,66 @@ package sourcing import ( "encoding/json" - . "launchpad.net/gocheck" + . "github.com/smartystreets/goconvey/convey" + "testing" ) -// The state for the test suite -type EventSourceIdTestSuite struct { -} +// Make sure we can turn an EventSourceId into a JSON value +func TestMarshallJSON(t *testing.T) { + Convey("Given we have an object with an id and a pointer to that id", t, func() { + id := NewEventSourceId() -// Setup the test suite -var _ = Suite(&EventSourceIdTestSuite{}) + testobject := &struct { + Id EventSourceId `json:"id"` + IdPtr *EventSourceId `json:"idPtr"` + }{ + Id: id, + IdPtr: &id, + } -// Make sure we can turn an EventSourceId into a JSON value -func (s *EventSourceIdTestSuite) TestMarshallJSON(c *C) { - id := NewEventSourceId() + Convey("When we marshall the object", func() { + b, err := json.Marshal(testobject) - t := &struct { - Id EventSourceId `json:"id"` - IdPtr *EventSourceId `json:"idPtr"` - }{ - Id: id, - IdPtr: &id, - } + Convey("Then there is no error", func() { + So(err, ShouldBeNil) + }) - b, err := json.Marshal(t) - c.Assert(err, IsNil) + Convey("And the object is marshalled correctly", func() { + So(string(b), ShouldEqual, "{\"id\":\""+testobject.Id.String()+"\",\"idPtr\":\""+testobject.IdPtr.String()+"\"}") + }) - c.Assert(string(b), Equals, "{\"id\":\""+t.Id.String()+"\",\"idPtr\":\""+t.IdPtr.String()+"\"}") + }) + }) } // Make sure we can turn an JSON value into an EventSourceId -func (s *EventSourceIdTestSuite) TestUnMarshallJSON(c *C) { - t := &struct { - Id EventSourceId `json:"id"` - IdPtr *EventSourceId `json:"idPtr"` - }{} - - id := NewEventSourceId() - data := []byte("{\"id\":\"" + id.String() + "\",\"idPtr\":\"" + id.String() + "\"}") - err := json.Unmarshal(data, &t) - c.Assert(err, IsNil) - - c.Assert(t.Id, Equals, id) - c.Assert(*t.IdPtr, Equals, id) +func TestUnMarshallJSON(t *testing.T) { + Convey("Given we have the JSON representation of an object with an id and a pointer to that id", t, func() { + + id := NewEventSourceId() + + testobject := &struct { + Id EventSourceId `json:"id"` + IdPtr *EventSourceId `json:"idPtr"` + }{} + + data := []byte("{\"id\":\"" + id.String() + "\",\"idPtr\":\"" + id.String() + "\"}") + + Convey("When we unmarshall the object", func() { + err := json.Unmarshal(data, &testobject) + + Convey("Then there is no error", func() { + So(err, ShouldBeNil) + }) + + Convey("The unmarshalled id is equal to the original one", func() { + So(testobject.Id, ShouldResemble, id) + }) + + Convey("And the unmarshalled pointer points to the id", func() { + So(*testobject.IdPtr, ShouldResemble, id) + // So(testobject.IdPtr, ShouldPointTo, &testobject.Id) //TODO + }) + }) + }) } diff --git a/sourcing/Hook_test.go b/sourcing/Hook_test.go deleted file mode 100644 index 1e0c18c..0000000 --- a/sourcing/Hook_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package sourcing - -import ( - "launchpad.net/gocheck" - "testing" -) - -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { - gocheck.TestingT(t) -} diff --git a/storage/Event.go b/storage/Event.go index 6705e40..201feb4 100644 --- a/storage/Event.go +++ b/storage/Event.go @@ -2,7 +2,7 @@ package storage import ( "fmt" - "github.com/pjvds/go-cqrs/sourcing" + "github.com/dominikmayer/go-cqrs/sourcing" "time" ) diff --git a/storage/EventName_test.go b/storage/EventName_test.go index dee165e..3939e5f 100644 --- a/storage/EventName_test.go +++ b/storage/EventName_test.go @@ -2,43 +2,70 @@ package storage import ( "encoding/json" - . "launchpad.net/gocheck" + . "github.com/smartystreets/goconvey/convey" + "testing" ) -// The state for the test suite -type EventNameTestSuite struct { +type TestStruct struct { + Name EventName `json:"name"` + NamePtr *EventName `json:"namePtr"` } -// Setup the test suite -var _ = Suite(&EventNameTestSuite{}) +var nameValue string = "Name value" -// Make sure we can turn an EventName into a JSON value -func (s *EventNameTestSuite) TestMarshallJSON(c *C) { - t := &struct { - Name EventName `json:"name"` - NamePtr *EventName `json:"namePtr"` - }{ - Name: *NewEventName("Name value"), - NamePtr: NewEventName("NamePtr value"), - } +var namePtrValue string = "NamePtr value" - b, err := json.Marshal(t) - c.Assert(err, IsNil) +var testEventName EventName = *NewEventName(nameValue) - c.Assert(string(b), Equals, "{\"name\":\"Name value\",\"namePtr\":\"NamePtr value\"}") +var testEventNamePtr *EventName = NewEventName(namePtrValue) + +var testobjectJson string = "{\"name\":\"" + nameValue + "\",\"namePtr\":\"" + namePtrValue + "\"}" + +func TestMarshalEventName(t *testing.T) { + Convey("Given we have an object with an EventName and a pointer to it and the correct string representation", t, func() { + + testobject := TestStruct{ + Name: testEventName, + NamePtr: testEventNamePtr, + } + + Convey("When we marshal the object", func() { + b, err := json.Marshal(testobject) + + Convey("Then there is no error", func() { + So(err, ShouldBeNil) + }) + + Convey("And the string matches the correct string representation", func() { + So(string(b), ShouldEqual, testobjectJson) + }) + }) + }) } // Make sure we can turn an JSON value into an EventName -func (s *EventNameTestSuite) TestUnMarshallJSON(c *C) { - t := &struct { - Name EventName `json:"name"` - NamePtr *EventName `json:"namePtr"` - }{} - - data := []byte("{\"name\":\"Name value\",\"namePtr\":\"NamePtr value\"}") - err := json.Unmarshal(data, &t) - c.Assert(err, IsNil) - - c.Assert(t.Name, Equals, *NewEventName("Name value")) - c.Assert(*t.NamePtr, Equals, *NewEventName("NamePtr value")) +func TestUnmarshalEventName(t *testing.T) { + Convey("Given we have the string representation of an object with an EventName and a pointer to it", t, func() { + + testobject := TestStruct{} + + data := []byte(testobjectJson) + + Convey("When we unmarshal the string representation", func() { + + err := json.Unmarshal(data, &testobject) + + Convey("Then there is no error", func() { + So(err, ShouldBeNil) + }) + + Convey("The EventName matches the original one", func() { + So(testobject.Name, ShouldResemble, testEventName) + }) + + Convey("And the pointer to EventName matches the original one", func() { + So(testobject.NamePtr, ShouldResemble, testEventNamePtr) + }) + }) + }) } diff --git a/storage/EventNamer.go b/storage/EventNamer.go index b6d0f66..b2fe4c1 100644 --- a/storage/EventNamer.go +++ b/storage/EventNamer.go @@ -1,7 +1,7 @@ package storage import ( - "github.com/pjvds/go-cqrs/sourcing" + "github.com/dominikmayer/go-cqrs/sourcing" "reflect" ) diff --git a/storage/EventNamer_test.go b/storage/EventNamer_test.go index d7aba86..2251d56 100644 --- a/storage/EventNamer_test.go +++ b/storage/EventNamer_test.go @@ -1,7 +1,8 @@ package storage import ( - . "launchpad.net/gocheck" + . "github.com/smartystreets/goconvey/convey" + "testing" ) type myEvent struct { @@ -9,31 +10,41 @@ type myEvent struct { Bar int } -func (s *EventNamerTestSuite) TestNewTypeEventNamerReturnsValue(c *C) { - result := NewTypeEventNamer() - c.Assert(result, NotNil) -} - -func (s *EventNamerTestSuite) TestGetEventName(c *C) { - event := myEvent{ - Foo: "baz", - Bar: 42, - } - - result := NewTypeEventNamer() - name := result.GetEventName(event) - - c.Assert(name, Equals, EventName("github.com/pjvds/go-cqrs/storage/myEvent")) -} - -func (s *EventNamerTestSuite) TestGetEventNameForPointer(c *C) { - event := &myEvent{ - Foo: "baz", - Bar: 42, - } - - result := NewTypeEventNamer() - name := result.GetEventName(event) - - c.Assert(name, Equals, EventName("github.com/pjvds/go-cqrs/storage/myEvent")) +func TestEventNamer(t *testing.T) { + Convey("When we request a new TypeEventNamer", t, func() { + result := NewTypeEventNamer() + + Convey("Then we should be given one", func() { + So(result, ShouldNotBeNil) + So(result, ShouldHaveSameTypeAs, &TypeEventNamer{}) + }) + + Convey("When we have an event 'myEvent' in the package 'github.com/dominikmayer/go-cqrs/storage'", func() { + event := myEvent{ + Foo: "baz", + Bar: 42, + } + Convey("And we request the event name", func() { + name := result.GetEventName(event) + + Convey("Then it should be 'github.com/dominikmayer/go-cqrs/storage/myEvent'", func() { + So(name, ShouldEqual, "github.com/dominikmayer/go-cqrs/storage/myEvent") + }) + }) + }) + + Convey("When we have a pointer to 'myEvent' in the package 'github.com/dominikmayer/go-cqrs/storage'", func() { + event := &myEvent{ + Foo: "baz", + Bar: 42, + } + Convey("And we request the event name", func() { + name := result.GetEventName(event) + + Convey("Then it should be 'github.com/dominikmayer/go-cqrs/storage/myEvent'", func() { + So(name, ShouldEqual, "github.com/dominikmayer/go-cqrs/storage/myEvent") + }) + }) + }) + }) } diff --git a/storage/EventStreamChange.go b/storage/EventStreamChange.go index f2b322d..38b0384 100644 --- a/storage/EventStreamChange.go +++ b/storage/EventStreamChange.go @@ -6,3 +6,19 @@ type EventStreamChange struct { To int64 Events []*Event } + +type EventStreamChangePersist struct { + StreamId string + From int64 + To int64 + Events []*Event +} + +func (e *EventStreamChange) GetPersistableObject() *EventStreamChangePersist { + return &EventStreamChangePersist{ + StreamId: e.StreamId.String(), + From: e.From, + To: e.To, + Events: e.Events, + } +} diff --git a/storage/EventStreamId.go b/storage/EventStreamId.go index f6cff8d..81abf6c 100644 --- a/storage/EventStreamId.go +++ b/storage/EventStreamId.go @@ -15,6 +15,14 @@ func NewEventStreamId() EventStreamId { return EventStreamId(*guid) } +/*func NewEventStreamIdFromString(streamId string) EventStreamId { + guid, err := uuid.ParseHex(streamId) + if err != nil { + panic(err) + } + return EventStreamId(*guid) +}*/ + func (id EventStreamId) String() string { guid := uuid.UUID(id) return guid.String() diff --git a/storage/Hook_test.go b/storage/Hook_test.go deleted file mode 100644 index a6f1c8d..0000000 --- a/storage/Hook_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package storage - -import ( - . "launchpad.net/gocheck" - "testing" -) - -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { - TestingT(t) -} - -// The state for the test suite -type EventNamerTestSuite struct { -} - -// Setup the test suite -var _ = Suite(&EventNamerTestSuite{}) diff --git a/storage/Repository.go b/storage/Repository.go index 08ee31f..fcb86bc 100644 --- a/storage/Repository.go +++ b/storage/Repository.go @@ -1,7 +1,7 @@ package storage import ( - "github.com/pjvds/go-cqrs/sourcing" + "github.com/dominikmayer/go-cqrs/sourcing" "time" ) diff --git a/storage/Repository_test.go b/storage/Repository_test.go index 6bc8f7d..ffb9f27 100644 --- a/storage/Repository_test.go +++ b/storage/Repository_test.go @@ -1,28 +1,30 @@ package storage -// import ( -// "github.com/pjvds/go-cqrs/sourcing" -// "github.com/pjvds/go-cqrs/storage/memory" -// . "launchpad.net/gocheck" -// ) +import ( +// "github.com/dominikmayer/go-cqrs/sourcing" +// "github.com/dominikmayer/go-cqrs/storage/memory" + . "launchpad.net/gocheck" + "fmt" +) -// // The state for the test suite -// type RepositoryTestSuite struct { -// } +// The state for the test suite +type RepositoryTestSuite struct { +} -// type TestInterceptor struct { -// TotalDispatchCount int -// LastDispatched *EventStreamChange -// } +//type TestInterceptor struct { +// TotalDispatchCount int +// LastDispatched *EventStreamChange +//} +// +//func (t *TestInterceptor) Dispatch(change *EventStreamChange) { +// t.LastDispatched = change +// t.TotalDispatchCount++ +//} -// func (t *TestInterceptor) Dispatch(change *EventStreamChange) { -// t.LastDispatched = change -// t.TotalDispatchCount++ -// } +//Setup the test suite +var _ = Suite(&RepositoryTestSuite{}) -// // Setup the test suite -// var _ = Suite(&RepositoryTestSuite{}) - -// func (s *RepositoryTestSuite) TestDispatchGetsCalledAfterAdd(c *C) { -// result := NewRepository(memory.NewMemoryBackend()) -// } +func (s *RepositoryTestSuite) TestDispatchGetsCalledAfterAdd(c *C) { + //result := NewRepository(memory.NewMemoryBackend()) + fmt.Printf("Hello world 2!") +} diff --git a/storage/eventstore/EventStore.go b/storage/eventstore/EventStore.go index c02cc86..aa2a187 100644 --- a/storage/eventstore/EventStore.go +++ b/storage/eventstore/EventStore.go @@ -5,8 +5,8 @@ import ( "encoding/json" "errors" "fmt" - "github.com/pjvds/go-cqrs/storage" - "github.com/pjvds/go-cqrs/storage/serialization" + "github.com/dominikmayer/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage/serialization" "net/http" "net/url" ) diff --git a/storage/eventstore/EventStore_test.go b/storage/eventstore/EventStore_test.go index 9b2fc05..7e564da 100644 --- a/storage/eventstore/EventStore_test.go +++ b/storage/eventstore/EventStore_test.go @@ -3,10 +3,10 @@ package eventstore import ( "flag" "fmt" - "github.com/pjvds/go-cqrs/storage" - "github.com/pjvds/go-cqrs/storage/serialization" - "github.com/pjvds/go-cqrs/tests/domain" - . "github.com/pjvds/go-cqrs/tests/events" + "github.com/dominikmayer/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage/serialization" + "github.com/dominikmayer/go-cqrs/tests/domain" + . "github.com/dominikmayer/go-cqrs/tests/events" . "launchpad.net/gocheck" "reflect" ) diff --git a/storage/memory/MemoryBackend.go b/storage/memory/MemoryBackend.go index be67a34..2af3fec 100644 --- a/storage/memory/MemoryBackend.go +++ b/storage/memory/MemoryBackend.go @@ -1,7 +1,7 @@ package memory import ( - . "github.com/pjvds/go-cqrs/storage" + . "github.com/dominikmayer/go-cqrs/storage" ) type MemoryBackend struct { @@ -22,6 +22,7 @@ func (m *MemoryBackend) WriteStream(change *EventStreamChange) error { } m.changes[change.StreamId] = append(changes, change) + Log.Debug("Changes: %v", m.changes) return nil } diff --git a/storage/memory/MemoryBackend_test.go b/storage/memory/MemoryBackend_test.go index d72fc69..bea72ad 100644 --- a/storage/memory/MemoryBackend_test.go +++ b/storage/memory/MemoryBackend_test.go @@ -1,8 +1,9 @@ package memory import ( + "testing" "encoding/json" - . "github.com/pjvds/go-cqrs/storage" + . "github.com/dominikmayer/go-cqrs/storage" . "launchpad.net/gocheck" "time" ) @@ -16,6 +17,8 @@ type myEvent struct { type MemoryBackendSuite struct { } +func TestMemoryBackend(t *testing.T) { TestingT(t) } + // Setup the test suite var _ = Suite(&MemoryBackendSuite{}) diff --git a/storage/mongodb/MongoDB.go b/storage/mongodb/MongoDB.go new file mode 100644 index 0000000..8a5150b --- /dev/null +++ b/storage/mongodb/MongoDB.go @@ -0,0 +1,68 @@ +package mongodb + +import ( + "errors" + . "github.com/dominikmayer/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage/serialization" + "labix.org/v2/mgo" + "labix.org/v2/mgo/bson" +) + +type MongoDB struct { + baseUrl string + database string + collection string +} + +func New(url string, database string, collection string, register *serialization.EventTypeRegister) *MongoDB { + // TODO do we need a BSON serializer? + return &MongoDB{ + baseUrl: url, + database: database, + collection: collection, + } +} + +func (store *MongoDB) WriteStream(change *EventStreamChange) error { + session, err := mgo.Dial(store.baseUrl) + //Log.Debug("Base-URL: %v", store.baseUrl) + if err != nil { + return err + } + defer session.Close() + + collection := session.DB(store.database).C(store.collection) + + //Log.Debug("Inserting data: %v", change) + return collection.Insert(change.GetPersistableObject()) +} + +func (store *MongoDB) ReadStream(streamId EventStreamId) ([]*Event, error) { + persistedEvents := make([]*EventStreamChangePersist, 0) + session, err := mgo.Dial(store.baseUrl) + if err != nil { + return nil, err + } + defer session.Close() + + collection := session.DB(store.database).C(store.collection) + + Log.Debug("Stream-ID: %v", streamId) + b := bson.M{"streamid": streamId.String()} + err = collection.Find(b).All(&persistedEvents) + if err != nil { + Log.Debug("Error: %v", err) + return nil, err + } + + numberOfEvents := len(persistedEvents) + if numberOfEvents > 1 { + Log.Debug("%v duplicate objects: %v", numberOfEvents, persistedEvents) + return nil, errors.New("Duplicate objects found") + } + + receivedEvents := persistedEvents[0].Events + Log.Debug("%v unpacked Events: %v", len(receivedEvents), receivedEvents) + + return receivedEvents, nil +} diff --git a/storage/mongodb/MongoDB_test.go b/storage/mongodb/MongoDB_test.go new file mode 100644 index 0000000..66a7ba2 --- /dev/null +++ b/storage/mongodb/MongoDB_test.go @@ -0,0 +1,78 @@ +package mongodb + +import ( + "testing" + //. "github.com/smartystreets/goconvey/convey" + + "flag" + "fmt" + "github.com/dominikmayer/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage/serialization" + "github.com/dominikmayer/go-cqrs/tests/domain" + . "github.com/dominikmayer/go-cqrs/tests/events" + . "launchpad.net/gocheck" + "reflect" +) + +type myEvent struct { + Foo string + Bar int +} + +var testMongoDB = flag.Bool("mongodb", true, "Include MongoDB tests") + +func init() { + flag.Parse() +} + +// The state for the test suite +type MongoDBTestSuite struct { + store *MongoDB + repository *storage.Repository +} + +func TestMongoDB(t *testing.T) { TestingT(t) } + +// Setup the test suite +var _ = Suite(&MongoDBTestSuite{}) + +func (s *MongoDBTestSuite) SetUpSuite(c *C) { + if !*testMongoDB { + c.Skip("-MongoDB not provided") + } + + register := serialization.NewEventTypeRegister() + namer := storage.NewTypeEventNamer() + + userCreatedType := reflect.TypeOf(UserCreated{}) + userCreatedName := namer.GetEventNameFromType(userCreatedType) + register.Register(userCreatedName, userCreatedType) + + usernameChangedType := reflect.TypeOf(UsernameChanged{}) + usernameChangedName := namer.GetEventNameFromType(usernameChangedType) + register.Register(usernameChangedName, usernameChangedType) + + store := New("localhost:27017", "test", "user", register) + s.store = store + + s.repository = storage.NewRepository(s.store, storage.NewNullEventDispatcher()) +} + +func (s *MongoDBTestSuite) TestSmoke(c *C) { + // Create a new domain object + toStore := domain.NewUser("pjvds") + for i := 0; i < 24; i++ { + toStore.ChangeUsername(fmt.Sprintf("pjvds%v", i)) + } + + err := s.repository.Add(toStore) + c.Assert(err, IsNil) + + events, err := s.store.ReadStream(storage.EventStreamId(toStore.Id())) + c.Assert(err, IsNil) + c.Assert(len(events), Equals, 25) + + namer := storage.NewTypeEventNamer() + userCreatedType := reflect.TypeOf(UserCreated{}) + c.Assert(events[0].Name, Equals, namer.GetEventNameFromType(userCreatedType)) +} diff --git a/storage/rethinkdb/RethinkDB.go b/storage/rethinkdb/RethinkDB.go new file mode 100644 index 0000000..78ed309 --- /dev/null +++ b/storage/rethinkdb/RethinkDB.go @@ -0,0 +1,67 @@ +package rethinkdb + +import ( + . "github.com/dominikmayer/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage/serialization" + r "github.com/dancannon/gorethink" +) + +type RethinkDB struct { + address string + database string + table string +} + +func New(url string, database string, table string, register *serialization.EventTypeRegister) *RethinkDB { + return &RethinkDB{ + address: url, // TODO: os.Getenv("RETHINKDB_URL") + database: database, + table: table, + } +} + +func (store *RethinkDB) WriteStream(change *EventStreamChange) error { + session, err := r.Connect(map[string]interface{}{ + "address": store.address, + "database": store.database, +}) + if err != nil { + return err + } + defer session.Close() + + _, err = r.Table(store.table).Insert(change.GetPersistableObject()).RunWrite(session) + Log.Debug("Change: %v, Error: %v", change, err) + return err +} + +func (store *RethinkDB) ReadStream(streamId EventStreamId) ([]*Event, error) { + session, err := r.Connect(map[string]interface{}{ + "address": store.address, + "database": store.database, +}) + if err != nil { + return nil, err + } + defer session.Close() + + row, err := r.Table(store.table).Filter(streamId).RunRow(session) + + Log.Debug("Stream-ID: %v", streamId) + if err != nil { + Log.Debug("Error: %v", err) + return nil, err + } + + var persistedEvent EventStreamChangePersist + err = row.Scan(&persistedEvent) + if err != nil { + Log.Debug("Error: %v", err) + return nil, err + } + + receivedEvents := persistedEvent.Events + Log.Debug("%v unpacked Events: %v", len(receivedEvents), receivedEvents) + + return receivedEvents, nil +} diff --git a/storage/rethinkdb/RethinkDB_test.go b/storage/rethinkdb/RethinkDB_test.go new file mode 100644 index 0000000..2dcb6c5 --- /dev/null +++ b/storage/rethinkdb/RethinkDB_test.go @@ -0,0 +1,78 @@ +package rethinkdb + +import ( + "testing" + //. "github.com/smartystreets/goconvey/convey" + + "flag" + "fmt" + "github.com/dominikmayer/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage/serialization" + "github.com/dominikmayer/go-cqrs/tests/domain" + . "github.com/dominikmayer/go-cqrs/tests/events" + . "launchpad.net/gocheck" + "reflect" +) + +type myEvent struct { + Foo string + Bar int +} + +var testRethinkDB = flag.Bool("rethinkdb", true, "Include RethinkDB tests") + +func init() { + flag.Parse() +} + +// The state for the test suite +type RethinkDBTestSuite struct { + store *RethinkDB + repository *storage.Repository +} + +func TestRethinkDB(t *testing.T) { TestingT(t) } + +// Setup the test suite +var _ = Suite(&RethinkDBTestSuite{}) + +func (s *RethinkDBTestSuite) SetUpSuite(c *C) { + if !*testRethinkDB { + c.Skip("-RethinkDB not provided") + } + + register := serialization.NewEventTypeRegister() + namer := storage.NewTypeEventNamer() + + userCreatedType := reflect.TypeOf(UserCreated{}) + userCreatedName := namer.GetEventNameFromType(userCreatedType) + register.Register(userCreatedName, userCreatedType) + + usernameChangedType := reflect.TypeOf(UsernameChanged{}) + usernameChangedName := namer.GetEventNameFromType(usernameChangedType) + register.Register(usernameChangedName, usernameChangedType) + + store := New("localhost:28015", "test", "user", register) + s.store = store + + s.repository = storage.NewRepository(s.store, storage.NewNullEventDispatcher()) +} + +func (s *RethinkDBTestSuite) TestSmoke(c *C) { + // Create a new domain object + toStore := domain.NewUser("pjvds") + for i := 0; i < 24; i++ { + toStore.ChangeUsername(fmt.Sprintf("pjvds%v", i)) + } + + err := s.repository.Add(toStore) + c.Assert(err, IsNil) + + events, err := s.store.ReadStream(storage.EventStreamId(toStore.Id())) + c.Assert(err, IsNil) + c.Assert(len(events), Equals, 25) + + namer := storage.NewTypeEventNamer() + userCreatedType := reflect.TypeOf(UserCreated{}) + c.Assert(events[0].Name, Equals, namer.GetEventNameFromType(userCreatedType)) +} diff --git a/storage/serialization/EventTypeRegister.go b/storage/serialization/EventTypeRegister.go index 1ae1cb8..6564931 100644 --- a/storage/serialization/EventTypeRegister.go +++ b/storage/serialization/EventTypeRegister.go @@ -1,8 +1,8 @@ package serialization import ( - "github.com/pjvds/go-cqrs/sourcing" - "github.com/pjvds/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/sourcing" + "github.com/dominikmayer/go-cqrs/storage" "reflect" ) diff --git a/storage/serialization/EventTypeRegister_test.go b/storage/serialization/EventTypeRegister_test.go index 8ad39f7..06b7474 100644 --- a/storage/serialization/EventTypeRegister_test.go +++ b/storage/serialization/EventTypeRegister_test.go @@ -1,70 +1,64 @@ package serialization import ( - "github.com/pjvds/go-cqrs/storage" - . "launchpad.net/gocheck" + "github.com/dominikmayer/go-cqrs/storage" + . "github.com/smartystreets/goconvey/convey" "reflect" + "testing" ) type AType struct{} type BType struct{} type CType struct{} -type EventTypeRegisterTestSuite struct { -} - -// Setup the test suite -var _ = Suite(&EventTypeRegisterTestSuite{}) - -func (suite *EventTypeRegisterTestSuite) SetUpSuite(c *C) { -} - -func (suite *EventTypeRegisterTestSuite) TestRegistersAlwaysElementTypes(c *C) { - aName := *storage.NewEventName("A") - bName := *storage.NewEventName("B") - cName := *storage.NewEventName("C") - - register := NewEventTypeRegister() - register.RegisterInstance(aName, AType{}) - register.RegisterInstance(bName, &BType{}) - - ctype := &CType{} - register.RegisterInstance(cName, &ctype) - - aType, _ := register.Get(aName) - bType, _ := register.Get(bName) - cType, _ := register.Get(cName) - - c.Assert(aType.Kind(), Equals, reflect.Struct) - c.Assert(bType.Kind(), Equals, reflect.Struct) - c.Assert(cType.Kind(), Equals, reflect.Struct) -} - -func (suite *EventTypeRegisterTestSuite) TestGetReturnsOkForKnownType(c *C) { - aName := *storage.NewEventName("A") - - register := NewEventTypeRegister() - register.RegisterInstance(aName, AType{}) - - _, ok := register.Get(aName) - c.Assert(ok, Equals, true) -} - -func (suite *EventTypeRegisterTestSuite) TestGetReturnsNOkForUnknownType(c *C) { - aName := *storage.NewEventName("A") - - register := NewEventTypeRegister() - - _, ok := register.Get(aName) - c.Assert(ok, Equals, false) -} - -func (suite *EventTypeRegisterTestSuite) TestGetReturnsType(c *C) { - aName := *storage.NewEventName("A") - - register := NewEventTypeRegister() - register.RegisterInstance(aName, AType{}) - - t, _ := register.Get(aName) - c.Assert(t, NotNil) +func TestEventTypeRegister(t *testing.T) { + Convey("Given a register and three EventNames A, B and C of types AType, BType and CType", t, func() { + register := NewEventTypeRegister() + + aName := *storage.NewEventName("A") + bName := *storage.NewEventName("B") + cName := *storage.NewEventName("C") + + Convey("When we try to get the type of A", func() { + _, notOk := register.Get(aName) + + Convey("Then Get should return 'not ok'/false", func() { + So(notOk, ShouldBeFalse) + }) + }) + + Convey("We register A by instance", func() { //TODO: Is A or B the pointer? + register.RegisterInstance(aName, AType{}) + }) + Convey("We register B by instance with a pointer type", func() { //TODO: Is A or B the pointer? + register.RegisterInstance(bName, &BType{}) + }) + Convey("We register C by instance with a variable of pointer type", func() { //TODO: Is A or B the pointer? + ctype := &CType{} + register.RegisterInstance(cName, &ctype) + }) + Convey("When we get the types", func() { + aType, okA := register.Get(aName) + bType, okB := register.Get(bName) + cType, okC := register.Get(cName) + + Convey("Then they should not be nil", func() { + So(aType, ShouldNotBeNil) + So(bType, ShouldNotBeNil) + So(cType, ShouldNotBeNil) + }) + + Convey("They should all be of kind Struct", func() { + So(aType.Kind(), ShouldEqual, reflect.Struct) + So(bType.Kind(), ShouldEqual, reflect.Struct) + So(cType.Kind(), ShouldEqual, reflect.Struct) + }) + + Convey("And Get should have returned 'ok'", func() { + So(okA, ShouldBeTrue) + So(okB, ShouldBeTrue) + So(okC, ShouldBeTrue) + }) + }) + }) } diff --git a/storage/serialization/Hook_test.go b/storage/serialization/Hook_test.go deleted file mode 100644 index e8e3173..0000000 --- a/storage/serialization/Hook_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package serialization - -import ( - "launchpad.net/gocheck" - "testing" -) - -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { - gocheck.TestingT(t) -} diff --git a/storage/serialization/JsonSerializer.go b/storage/serialization/JsonSerializer.go index d4fc5b8..4962da1 100644 --- a/storage/serialization/JsonSerializer.go +++ b/storage/serialization/JsonSerializer.go @@ -4,7 +4,7 @@ import ( "encoding/json" "errors" "fmt" - "github.com/pjvds/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage" "reflect" "time" ) diff --git a/storage/serialization/JsonSerializer_test.go b/storage/serialization/JsonSerializer_test.go index 35098ae..ba29353 100644 --- a/storage/serialization/JsonSerializer_test.go +++ b/storage/serialization/JsonSerializer_test.go @@ -1,9 +1,10 @@ package serialization import ( - "github.com/pjvds/go-cqrs/storage" - . "launchpad.net/gocheck" + "github.com/dominikmayer/go-cqrs/storage" + . "github.com/smartystreets/goconvey/convey" "reflect" + "testing" "time" ) @@ -12,17 +13,7 @@ type FooEvent struct { Bar int } -type JsonSerializerTestSuite struct { - fooEventType reflect.Type - fooEventName storage.EventName - - serializer *JsonSerializer -} - -// Setup the test suite -var _ = Suite(&JsonSerializerTestSuite{}) - -func (suite *JsonSerializerTestSuite) SetUpSuite(c *C) { +func TestSerialize(t *testing.T) { namer := storage.NewTypeEventNamer() event := new(FooEvent) @@ -32,39 +23,56 @@ func (suite *JsonSerializerTestSuite) SetUpSuite(c *C) { types := NewEventTypeRegister() types.Register(eventName, eventType) - suite.fooEventName = eventName - suite.fooEventType = eventType - suite.serializer = NewJsonSerializer(types) -} + serializer := NewJsonSerializer(types) -func (suite *JsonSerializerTestSuite) TestSerialize(c *C) { - expectedJson := "{\"eventId\":\"25f7fdb6-5ef9-47b0-55a1-b9160ce37730\",\"name\":\"github.com/pjvds/go-cqrs/storage/serialization/FooEvent\",\"sequence\":0,\"timestamp\":\"2011-02-01T12:32:40-05:00\",\"payload\":{\"Foo\":\"\",\"Bar\":0}}" + Convey("Given an event and its JSON", t, func() { + expectedJson := "{\"eventId\":\"25f7fdb6-5ef9-47b0-55a1-b9160ce37730\",\"name\":\"github.com/dominikmayer/go-cqrs/storage/serialization/FooEvent\",\"sequence\":0,\"timestamp\":\"2011-02-01T12:32:40-05:00\",\"payload\":{\"Foo\":\"\",\"Bar\":0}}" - timestamp, _ := time.Parse(time.RFC3339, "2011-02-01T12:32:40-05:00") + timestamp, _ := time.Parse(time.RFC3339, "2011-02-01T12:32:40-05:00") - eventId, err := storage.ParseEventId("\"25f7fdb6-5ef9-47b0-55a1-b9160ce37730\"") - c.Assert(err, IsNil) + eventId, err := storage.ParseEventId("\"25f7fdb6-5ef9-47b0-55a1-b9160ce37730\"") + So(err, ShouldBeNil) - event := new(FooEvent) + event := new(FooEvent) - envelope := storage.NewEvent(*eventId, suite.fooEventName, storage.NewEventSequence(0), timestamp, event) - data, err := suite.serializer.Serialize(envelope) + envelope := storage.NewEvent(*eventId, eventName, storage.NewEventSequence(0), timestamp, event) - c.Assert(err, IsNil) + Convey("When we serialize the event", func() { + data, err := serializer.Serialize(envelope) - actualJson := string(data) - c.Assert(actualJson, Equals, expectedJson) -} + Convey("Then there should be no errors", func() { + So(err, ShouldBeNil) + }) + + Convey("And the serialized JSON should match the expected one", func() { + actualJson := string(data) + So(actualJson, ShouldEqual, expectedJson) + }) + }) + }) + + Convey("Given", func() { + json := "{\"eventId\":\"25f7fdb6-5ef9-47b0-55a1-b9160ce37730\",\"name\":\"github.com/dominikmayer/go-cqrs/storage/serialization/FooEvent\",\"sequence\":0,\"timestamp\":\"2011-02-01T12:32:40-05:00\",\"payload\":{\"Foo\":\"hello world\",\"Bar\":42}}" + + Convey("Given", func() { + event, err := serializer.Deserialize(eventName, []byte(json)) + + Convey("Then there is no error", func() { + So(err, ShouldBeNil) + }) -func (suite *JsonSerializerTestSuite) TestDerialize(c *C) { - json := "{\"eventId\":\"25f7fdb6-5ef9-47b0-55a1-b9160ce37730\",\"name\":\"github.com/pjvds/go-cqrs/storage/serialization/FooEvent\",\"sequence\":0,\"timestamp\":\"2011-02-01T12:32:40-05:00\",\"payload\":{\"Foo\":\"hello world\",\"Bar\":42}}" - serializer := suite.serializer + Convey("The data was retrieved", func() { + So(event, ShouldNotBeNil) + }) - event, err := serializer.Deserialize(suite.fooEventName, []byte(json)) - c.Assert(err, IsNil) - c.Assert(event, NotNil) - c.Assert(event.Data, FitsTypeOf, new(FooEvent)) + Convey("It has the correct type", func() { + So(event.Data, ShouldHaveSameTypeAs, new(FooEvent)) + }) - c.Assert(event.Data.(*FooEvent).Foo, Equals, "hello world") - c.Assert(event.Data.(*FooEvent).Bar, Equals, 42) + Convey("And the content was correctly deserialized", func() { + So(event.Data.(*FooEvent).Foo, ShouldEqual, "hello world") + So(event.Data.(*FooEvent).Bar, ShouldEqual, 42) + }) + }) + }) } diff --git a/storage/serialization/Serializer.go b/storage/serialization/Serializer.go index 95ddacc..90df070 100644 --- a/storage/serialization/Serializer.go +++ b/storage/serialization/Serializer.go @@ -1,7 +1,7 @@ package serialization import ( - "github.com/pjvds/go-cqrs/storage" + "github.com/dominikmayer/go-cqrs/storage" ) type Serializer interface { diff --git a/tests/Sourcing_test.go b/tests/Sourcing_test.go index 48fb72c..ba530c1 100644 --- a/tests/Sourcing_test.go +++ b/tests/Sourcing_test.go @@ -1,90 +1,66 @@ package tests import ( - "github.com/pjvds/go-cqrs/sourcing" - "github.com/pjvds/go-cqrs/tests/domain" - "github.com/pjvds/go-cqrs/tests/events" - . "launchpad.net/gocheck" + "github.com/dominikmayer/go-cqrs/sourcing" + "github.com/dominikmayer/go-cqrs/tests/domain" + "github.com/dominikmayer/go-cqrs/tests/events" + . "github.com/smartystreets/goconvey/convey" "testing" ) -// Hook up gocheck into the "go test" runner. -func Test(t *testing.T) { - InitLogging() - TestingT(t) -} - -// The state for the test suite -type AppTestSuite struct { -} +func TestStateChangesAreRepresentedByEvents(t *testing.T) { -// Setup the test suite -var _ = Suite(&AppTestSuite{}) + Convey("Given we create a new user 'pjvds'", t, func() { + user := domain.NewUser("pjvds") -func (s *AppTestSuite) TestStateChangesAreRepresentedByEvents(c *C) { - // Create a new domain object - user := domain.NewUser("pjvds") - c.Assert(user.Username, Equals, "pjvds") + Convey("Then the username should be 'pjvds'", func() { + So(user.Username, ShouldEqual, "pjvds") + }) - // We created a new user, this should be - // captured by an event. - c.Assert(len(user.Events()), Equals, 1) + Convey("And the creation should be captured by an event", func() { + So(len(user.Events()), ShouldEqual, 1) + }) - // Change the username of the user - user.ChangeUsername("wwwouter") - c.Assert(user.Username, Equals, "wwwouter") + Convey("When we change the username to 'wwwouter'", func() { + user.ChangeUsername("wwwouter") - // We changed the username, this should be - // captured by an event. - c.Assert(len(user.Events()), Equals, 2) + Convey("Then this should also be captured by an event", func() { + So(len(user.Events()), ShouldEqual, 2) + }) + }) + }) } -func (s *AppTestSuite) TestDomainObjectCanBeBuildFromHistory(c *C) { - // The id of our event source that we will rebuild from history. - sourceId, _ := sourcing.ParseEventSourceId("0791d279-664d-458e-bf60-567ade140832") - - // The full history for the User domain object - history := []sourcing.Event{ - // It was first created - events.UserCreated{ - Username: "pjvds", - }, - // Then the username was changed - events.UsernameChanged{ - OldUsername: "pjvds", - NewUsername: "wwwouter", - }, - } - - // Create a new User domain object from history - user := domain.NewUserFromHistory(sourceId, history) - - // It should not have the initial state. - c.Assert(user.Username, Not(Equals), "pjvds") - - // It should have the latest state. - c.Assert(user.Username, Equals, "wwwouter") -} - -func (s *AppTestSuite) BenchmarkRebuildUserFromHistory(c *C) { - // The full history for the User domain object - sourceId, _ := sourcing.ParseEventSourceId("0791d279-664d-458e-bf60-567ade140832") - - // The full history for the User domain object - history := []sourcing.Event{ - // It was first created - events.UserCreated{ - Username: "pjvds", - }, - // Then the username was changed - events.UsernameChanged{ - OldUsername: "pjvds", - NewUsername: "wwwouter", - }, - } - - for i := 0; i < c.N; i++ { - // Create a new User domain object from history - domain.NewUserFromHistory(sourceId, history) - } +func TestDomainObjectCanBeBuildFromHistory(t *testing.T) { + + Convey("Given the user and the name changes from the last test", t, func() { + + // The id of our event source that we will rebuild from history. + sourceId, _ := sourcing.ParseEventSourceId("0791d279-664d-458e-bf60-567ade140832") + + // The full history for the User domain object + history := []sourcing.Event{ + // It was first created + events.UserCreated{ + Username: "pjvds", + }, + // Then the username was changed + events.UsernameChanged{ + OldUsername: "pjvds", + NewUsername: "wwwouter", + }, + } + + Convey("When we create a new User domain object from the event history", func() { + user := domain.NewUserFromHistory(sourceId, history) + + Convey("Then the username should not be 'pjvds'", func() { + So(user.Username, ShouldNotEqual, "pjvds") + }) + + Convey("But it should be 'wwwouter'", func() { + So(user.Username, ShouldEqual, "wwwouter") + }) + }) + }) } diff --git a/tests/domain/User.go b/tests/domain/User.go index feec3f3..e7dd486 100644 --- a/tests/domain/User.go +++ b/tests/domain/User.go @@ -2,8 +2,8 @@ package domain import ( "errors" - "github.com/pjvds/go-cqrs/sourcing" - "github.com/pjvds/go-cqrs/tests/events" + "github.com/dominikmayer/go-cqrs/sourcing" + "github.com/dominikmayer/go-cqrs/tests/events" ) // Holds the state of our user. Note that the