I try to get a MongoTemplate
(Spring Data) worked with my Spock spec test. I use Kotlin as language for the business logic.
Please see my specification logic:
@SpringBootTest
class BookingServiceSpec extends Specification {
BookingService bookingService;
BookingEntity bookingEntity
CustomerEntity customerEntity
MongoTemplate mongoTemplate;
def setup() {
bookingEntity = GroovyMock(BookingEntity)
customerEntity = GroovyMock(CustomerEntity)
mongoTemplate = Mock()
bookingService = new BookingService(mongoTemplate)
customerEntity.getEmail() >> "test@test.com"
mongoTemplate.find(!null, !null, !null) >> List.of(bookingEntity)
}
def "should return a list of bookings if asked for bookings for a customer"() {
when: "booking service is used to find bookings for a given customer"
List<BookingEntity> bookings = bookingService.getBookings(customerEntity)
then: "it should call the find method of the mongo template and return a list of booking entities"
1 * mongoTemplate.find(!null, !null, !null)
}
}
Running this code throws an IllegalStateException
with detail:
java.lang.IllegalStateException: mongoTemplate.find(query…::class.java, "bookings") must not be null
at com.nomadsolutions.areavr.booking.BookingService.getBookings(BookingService.kt:22)
at com.nomadsolutions.areavr.booking.BookingServiceSpec.should return a list of bookings if asked for bookings for a customer(BookingServiceSpec.groovy:37)
The entity data classes are defined like this:
data class CustomerEntity(val surname: String, val name: String, val email: String)
data class BookingEntity(val customerEntity: CustomerEntity, val date: Date)
And here is the business logic:
@Service
class BookingService(var mongoTemplate: MongoTemplate) {
fun addBooking(booking: BookingEntity) {
mongoTemplate.insert(booking)
}
fun getBookings(customerEntity: CustomerEntity): List<BookingEntity> {
val query = Query()
query.addCriteria(Criteria.where("customer.email").`is`(customerEntity.email))
return mongoTemplate.find(query, BookingEntity::class.java, "bookings")
}
}
I found out that the stubbing for customerEntity
is not working properly since customerEntity.email
is returning null
in the logic while debugging via test run.
I'd love to continue with Spock but it seems to block me from testing fast since I have to care about things like this.
Remove this line from setup()
method:
mongoTemplate.find(!null, !null, !null) >> List.of(bookingEntity)
And change the interaction test in the then
section of the test case in this way:
then: 'it should call the find method of the mongo template and return a list of booking entities'
1 * mongoTemplate.find(!null, !null, !null) >> [bookingEntity]
It is because when you are mocking and stubbing the same method call (mongoTemplate.find()
in your case) it should happen in the same interaction.
You can read more about that in the documentation.