func TestInMemoryEventStreamRepository(t *testing.T) {
	typeRegistry := cqrs.NewTypeRegistry()
	persistance := cqrs.NewInMemoryEventStreamRepository()
	repository := cqrs.NewRepository(persistance, typeRegistry)

	hashedPassword, err := GetHashForPassword("$ThisIsMyPassword1")
	accountID := "5058e029-d329-4c4b-b111-b042e48b0c5f"

	if err != nil {
		t.Fatal("Error: ", err)
	}

	log.Println("Get hash for user...")

	log.Println("Create new account...")
	account := NewAccount("John", "Snow", "*****@*****.**", hashedPassword, 0.0)
	account.SetID(accountID)
	account.ChangePassword("$ThisIsANOTHERPassword")
	if err := repository.Save(account, "correlationID"); err != nil {
		t.Fatal(err)
	}

	accountFromHistory, err := NewAccountFromHistory(accountID, repository)
	if err != nil {
		t.Fatal(err)
	}

	if string(accountFromHistory.PasswordHash) != string(account.PasswordHash) {
		t.Fatal("Expected PasswordHash to match")
	}

	if events, err := persistance.AllIntegrationEventsEverPublished(); err != nil {
		t.Fatal(err)
	} else {
		log.Println(events)
	}

	correlationEvents, err := persistance.GetIntegrationEventsByCorrelationID("correlationID")
	if err != nil {
		t.Fatal(err)
	}

	if len(correlationEvents) == 0 {
		t.Fatal("Expeced correlation events")
	}

	log.Println("GetIntegrationEventsByCorrelationID")
	for _, correlationEvent := range correlationEvents {
		log.Println(correlationEvent)
	}
}
Exemplo n.º 2
0
func TestScenario(t *testing.T) {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	// Type Registry
	typeRegistry := cqrs.NewTypeRegistry()

	// Event sourcing
	persistance := cqrs.NewInMemoryEventStreamRepository()
	bus := cqrs.NewInMemoryEventBus()
	repository := cqrs.NewRepositoryWithPublisher(persistance, bus, typeRegistry)
	typeRegistry.RegisterAggregate(&Account{}, AccountCreatedEvent{}, EmailAddressChangedEvent{}, AccountCreditedEvent{}, AccountDebitedEvent{}, PasswordChangedEvent{})

	// Read Models
	readModel := NewReadModelAccounts()
	usersModel := NewUsersModel()

	// Command Handlers
	commandBus := cqrs.NewInMemoryCommandBus()
	commandDispatcher := cqrs.NewCommandDispatchManager(commandBus, typeRegistry)
	RegisterCommandHandlers(commandDispatcher, repository)

	// Integration events
	eventDispatcher := cqrs.NewVersionedEventDispatchManager(bus, typeRegistry)
	integrationEventsLog := cqrs.NewInMemoryEventStreamRepository()
	RegisterIntegrationEventHandlers(eventDispatcher, integrationEventsLog, readModel, usersModel)

	commandDispatcherStopChannel := make(chan bool)
	eventDispatcherStopChannel := make(chan bool)
	go commandDispatcher.Listen(commandDispatcherStopChannel, false)
	go eventDispatcher.Listen(eventDispatcherStopChannel, false)

	log.Println("Dump models")
	log.Println(readModel)
	log.Println(usersModel)

	log.Println("Find an account")
	readModelAccount := readModel.Accounts[accountID]
	log.Println(readModelAccount)

	log.Println("Find a user")
	user := usersModel.Users[accountID]
	log.Println(user)

	hashedPassword, err := GetHashForPassword("$ThisIsMyPassword1")
	if err != nil {
		t.Fatal("Error: ", err)
	}

	log.Println("Create new account...")
	createAccountCommand := cqrs.CreateCommand(
		CreateAccountCommand{"John", "Snow", "*****@*****.**", hashedPassword, 0.0})
	commandBus.PublishCommands([]cqrs.Command{createAccountCommand})

	log.Println("Dump models")
	log.Println(readModel)
	log.Println(usersModel)

	log.Println("Change Password")
	changePasswordCommand := cqrs.CreateCommand(
		ChangePasswordCommand{accountID, "$ThisIsANOTHERPassword"})
	commandBus.PublishCommands([]cqrs.Command{changePasswordCommand})

	log.Println("Change email address and credit the account")
	changeEmailAddressCommand := cqrs.CreateCommand(
		ChangeEmailAddressCommand{accountID, "*****@*****.**"})
	creditAccountCommand := cqrs.CreateCommand(
		CreditAccountCommand{accountID, 50})
	creditAccountCommand2 := cqrs.CreateCommand(
		CreditAccountCommand{accountID, 50})
	commandBus.PublishCommands([]cqrs.Command{
		changeEmailAddressCommand,
		creditAccountCommand,
		creditAccountCommand2})

	log.Println("Dump models")
	log.Println(readModel)
	log.Println(usersModel)

	log.Println("Change the email address, credit 150, debit 200")
	lastEmailAddress := "*****@*****.**"
	changeEmailAddressCommand = cqrs.CreateCommand(
		ChangeEmailAddressCommand{accountID, lastEmailAddress})
	creditAccountCommand = cqrs.CreateCommand(
		CreditAccountCommand{accountID, 150})
	debitAccountCommand := cqrs.CreateCommand(
		DebitAccountCommand{accountID, 200})
	commandBus.PublishCommands([]cqrs.Command{
		changeEmailAddressCommand,
		creditAccountCommand,
		debitAccountCommand})

	log.Println("Dump models")
	log.Println(readModel)
	log.Println(usersModel)

	time.Sleep(300 * time.Millisecond)
	log.Println("Dump history - integration events")
	if history, err := repository.GetEventStreamRepository().AllIntegrationEventsEverPublished(); err != nil {
		t.Fatal(err)
	} else {
		for _, event := range history {
			log.Println(event)
		}
	}

	log.Println("GetIntegrationEventsByCorrelationID")
	correlationEvents, err := repository.GetEventStreamRepository().GetIntegrationEventsByCorrelationID(debitAccountCommand.CorrelationID)
	if err != nil || len(correlationEvents) == 0 {
		t.Fatal(err)
	}

	for correlationEvent := range correlationEvents {
		log.Println(correlationEvent)
	}

	log.Println("Load the account from history")
	account, error := NewAccountFromHistory(accountID, repository)
	if error != nil {
		t.Fatal(error)
	}

	// All events should have been replayed and the email address should be the latest
	log.Println("Dump models")
	log.Println(account)
	log.Println(readModel)
	log.Println(usersModel)

	if account.EmailAddress != lastEmailAddress {
		t.Fatal("Expected emailaddress to be ", lastEmailAddress)
	}

	if account.Balance != readModel.Accounts[accountID].Balance {
		t.Fatal("Expected readmodel to be synced with write model")
	}

	eventDispatcherStopChannel <- true
	commandDispatcherStopChannel <- true
}