lateinit property has not been initialized in aggregate

3,768 views
Skip to first unread message

Altug Sahin

unread,
Jan 21, 2018, 11:04:47 AM1/21/18
to Axon Framework Users
Hello,

I have a user domain aggregate which handles commands like, create, activate, change password. When I run the test I get the passwordEncoder not initialized exception. Why is that passwordEncoder bean not injected into User aggregate in test?

Then ran the web app and send command via Spring mvc, command is handled in user aggregate with no error.

Here is the simplified setup:



// Security.kt

@Configuration
class SecurityConfig {

@Bean
fun passwordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}

}

// User.kt

@Aggregate
class User {

@AggregateIdentifier
private lateinit var id: UserId

@Autowired
lateinit var passwordEncoder: PasswordEncoder

    // removed other crap
}


// UserTests.kt

class UserTests {

private lateinit var fixture: AggregateTestFixture<User>
private val userId = UserId()


@Before
fun setUp() {
fixture = AggregateTestFixture<User>(User::class.java)
}


fun tesChangeUserPassword() {
fixture.given(UserCreatedEvent(userId, "em...@email.com", "password"))
.`when`(ChangeUserPasswordCommand(userId, "password", "new password"))
.expectEvents(UserChangedPasswordEvent(userId, "new password"))
}
}

// Running the test above, gives me this exception

org.axonframework.test.AxonAssertionError: The published events do not match the expected events

Expected                                               |  Actual
-------------------------------------------------------|-------------------------------------------------------
com.testapp.domain.UserChangedPasswordEvent <|> 

A probable cause for the wrong chain of events is an exception that occurred while handling the command.
kotlin.UninitializedPropertyAccessException: lateinit property passwordEncoder has not been initialized

jan.ga...@holisticon.de

unread,
Jan 21, 2018, 1:26:08 PM1/21/18
to Axon Framework Users
since the fixture test is no spring test, you have to manually "fake" the injection

fixture.registerInjectableResource(passwordEncoderMock)

Altug Sahin

unread,
Jan 21, 2018, 2:32:25 PM1/21/18
to Axon Framework Users
BTW - I also tried running tests with spring runner and spring boot test, it didn't work either.

@RunWith(SpringRunner::class)
@SpringBootTest

I'll mock it as you suggested.

Thanks

Steven van Beelen

unread,
Jan 22, 2018, 3:39:51 AM1/22/18
to axonfr...@googlegroups.com
Hi Altug, Jan,

Axon Framework works with ParameterResolvers to resolve parameters for you message handling functions (like @EventHandler and @CommandHandler annotated functions).
Additionally, it contains a SpringBeanParameterResolver, which thus wires a Spring Bean into your command/event/query handler directly.
This is typically the way to go to wire a service into your Aggregate.

Wiring it through the @Autowired annotation as you've done Altug is at this point not completely supported.
I believe it has something to do in combination with Event Sourcing (obviously guessing you're doing Event Sourcing), as the `EventSourcingRepository` will recreate an Aggregate based on the events stored, without doing any Spring specific autowiring.
So, rather than having the `@Autowired lateinit var passwordEncoder: PasswordEncoder`, you can put that service directly in your Command/Event handling function as another parameter.

For testing, Jan his suggestion is definitely correct.
you need to register that service as a resource to the Test Fixture.
Otherwise it will not be wired for you.

Hope this helps!

Cheers,
Steven

--
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.
Reply all
Reply to author
Forward
0 new messages