With Spring Boot 3 JPA (Kotlin), I have an entity with an id property that is auto-generated. Now I have code which converts such an entity to a DTO (and the id is important in that context). How can I inject an id into the entity to unit test that code? (I don't want to use a heavyweight test with database). The constructor does not allow for passing the id, and I don't want to change the production code.
@Entity
@Table(name = "users")
data class User(
@Column(name = "created_at", nullable = false)
val createdAt: Instant,
){
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private var id: Int = 0
}
** EDIT: ** I noticed that in the original question the id field was not private. Then I can just assign the id from the outside during my test. I intended to ask about when the id is private, which is the only interesting scenario. I updated the code example accordingly. Sorry for the glitch.
My circumstance is different, but you should be able to take ideas from this approach.
When instantiating the test class, the following function creates a mock Respository
which for my purposes simply stores entities in a MutableMap
, with just one other function mocked, the findById(..)
EDIT: following OP's edit You could use reflection to set the private field. Code sample below updated:
private val savedAppointmentsById = mutableMapOf<RULID, MemberAppointment>()
private fun createSemiStatefulAppointmentRepositoryMock(): AppointmentRepository {
val repository: AppointmentRepository = mockk(relaxed = false)
savedAppointmentsById.clear()
every { repository.save(any()) } answers {
val appointment = firstArg<MemberAppointment>()
// here you would do something like:
val id = "new id"
appointment::class.java.getDeclaredField("id").let {
it.isAccessible = true
it.set(appointment, id)
}
savedAppointmentsById.put(appointment.id, appointment)
appointment
}
every { repository.findById(any()) } answers {
Optional.ofNullable(savedAppointmentsById.get(firstArg<RULID>()))
}
return repository
}