Search code examples
javaunit-testingtestinggroovyspock

Why does my test not work when splitting mocking and stubbing?


I struggle with Spock/Groovy testing. Don't know why but in WHEN section, I cannot check number of calls and checking the value at once.. If I check one of them separatly all works fine!

This test passed:

def "should throw AppointmentNotFoundException when appointment do not exist" () {
  given:
  long nonExistingAppointmentId = 69L

  when:
  appointmentRepository.findById(nonExistingAppointmentId) >> { throw new AppointmentNotFoundException("Appointment with id " + nonExistingAppointmentId + " not found") }
  findAppointmentQueryHandler.handle(nonExistingAppointmentId)

  then:
  thrown(AppointmentNotFoundException)
}

Also this one passed without any problem:

def "should throw AppointmentNotFoundException when appointment do not exist" () {
  given:
  long nonExistingAppointmentId = 69L

  when:
  appointmentRepository.findById(nonExistingAppointmentId) >> { throw new AppointmentNotFoundException("Appointment with id " + nonExistingAppointmentId + " not found") }
  findAppointmentQueryHandler.handle(nonExistingAppointmentId)

  then:
  1 * appointmentRepository.findById(69L)
}

But if I try to make 1 test to check all of it then I have error

def "should throw AppointmentNotFoundException when appointment do not exist" () {
  given:
  long nonExistingAppointmentId = 69L

  when:
  appointmentRepository.findById(nonExistingAppointmentId) >> { throw new AppointmentNotFoundException("Appointment with id " + nonExistingAppointmentId + " not found") }
  findAppointmentQueryHandler.handle(nonExistingAppointmentId)

  then:
  1 * appointmentRepository.findById(69L)
  thrown(AppointmentNotFoundException)
}

Error:

Expected exception of type 'com.bbc.anotherhospital.exceptions.AppointmentNotFoundException', but no exception was thrown
    at org.spockframework.lang.SpecInternals.checkExceptionThrown(SpecInternals.java:84)
    at org.spockframework.lang.SpecInternals.thrownImpl(SpecInternals.java:71)
    at com.bbc.anotherhospital.appointment.handlers.FindAppointmentQueryHandlerSpec.should throw AppointmentNotFoundException when appointment do not exist

First I think that I have problem in my code or smth.. But application works fine, tested in Postman.

Anybody have idea why is it behaving this way?

My pom:

<dependency>
  <groupId>org.apache.groovy</groupId>
  <artifactId>groovy-all</artifactId>
  <version>4.0.15</version>
  <type>pom</type>
</dependency>
<dependency>
  <groupId>org.spockframework</groupId>
  <artifactId>spock-core</artifactId>
  <version>2.4-M1-groovy-4.0</version>
  <scope>test</scope>
</dependency>

Solution

  • I had to add things so I could run your examples, but does:

    class TestSpec extends Specification {
    
        def "should throw AppointmentNotFoundException when appointment do not exist" () {
            given:
            AppointmentRepository appointmentRepository = Mock()
            FindAppointmentQueryHandler findAppointmentQueryHandler = new FindAppointmentQueryHandler(appRepository: appointmentRepository)
            long nonExistingAppointmentId = 69L
    
            when:
            findAppointmentQueryHandler.handle(nonExistingAppointmentId)
    
            then:
            def ex = thrown(AppointmentNotFoundException)
            ex.message == "Appointment with id $nonExistingAppointmentId not found"
    
            1 * appointmentRepository.findById(69L) >> {
                throw new AppointmentNotFoundException("Appointment with id " + nonExistingAppointmentId + " not found")
            }
        }
    
        static class FindAppointmentQueryHandler {
    
            AppointmentRepository appRepository
    
            String handle(long id) {
                appRepository.findById(id)
            }
        }
    
        static class AppointmentRepository {
    
            String findById(long id) {
                "called $id"
            }
        }
    
        static class AppointmentNotFoundException extends RuntimeException {
    
            AppointmentNotFoundException(String message) {
                super(message)
            }
        }
    }
    

    work?