Testing database calls in Ratpack

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Testing database calls in Ratpack

Nick P
Hi,

I am attempting to write a simple test using ExecHarness that calls my save method on a list of objects, I then try to use my fetchAll method to check that this has worked.

When I run my tests it seems in my given block it isn't actually doing anything as in the expect I get the error "cannot invoke method fetchAll on null object"

Here is my test

class HospitalServiceImplementationSpec extends Specification {

    @AutoCleanup
    ExecHarness execHarness = ExecHarness.harness()

    String id = UUID.randomUUID().toString()

    private static final def hospitals = [
            new Hospital(id: '79dfed0c-13f1-4e9c-b472-0fa857355bef', name: "Test Hospital", employees: "2500", address: "Test Address"),
            new Hospital(id: '79dfed0c-13f1-4e9c-b472-0fa857355bed', name: "Test Hospital", employees: "2500", address: "Test Address"),
            new Hospital(id: '79dfed0c-13f1-4e9c-b472-0fa857355bee', name: "Test Hospital", employees: "2500", address: "Test Address")
    ]

    @Inject
    HospitalServiceImplementation store

    void "Should save and return a list of hospitals"() {
        given:
        execHarness.yield {
            hospitals.each {
                hospital -> store.save(hospital)
            }
        }

        expect:
        execHarness.yieldSingle {
            store.fetchAll()
        }.value == hospitals
    }
}

And here are the two methods i am testing, the code works fine when I run my project just having issues testing.

  @Override
    Promise<List<Hospital>> fetchAll() {
        Blocking.get {
            sql.rows("select * from hospitals").collect { GroovyRowResult result ->
                String instanceJson = result.getAt(1)
                Hospital instance = mapper.readValue(instanceJson, Hospital)
                return instance
            }
        }
    }

    @Override
    Operation save(Hospital hospital) {
        Blocking.get {
            sql.execute "INSERT INTO hospitals (id, hospital_information) VALUES (${hospital.id}, ${JsonObjectMapper.mapObjectToJson(hospital)})"
        }.operation()
    }

rus
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

rus
How are you initializing `HospitalServiceImplementation store`?  It's annotated with @Inject but what's doing the injection?
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

Nick P
Here is my full class

class HospitalServiceImplementation implements HospitalService {

    @Inject Sql sql
    @Inject ObjectMapper mapper

    @Override
    Promise<List<Hospital>> fetchAll() {
        Blocking.get {
            sql.rows("select * from hospitals").collect { GroovyRowResult result ->
                String instanceJson = result.getAt(1)
                Hospital instance = mapper.readValue(instanceJson, Hospital)
                return instance
            }
        }
    }

    @Override
    Operation save(Hospital hospital) {
        Blocking.get {
            sql.execute "INSERT INTO hospitals (id, hospital_information) VALUES (${hospital.id}, ${JsonObjectMapper.mapObjectToJson(hospital)})"
        }.operation()
    }
}

Does that make more sense now?
rus
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

rus
I meant in your Specification.  There is nothing that sets the store variable.
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

Nick P
I thought by injecting the class I could then use its methods in my test, is this not correct?
rus
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

rus
Yes, but what's injecting the class?
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

Nick P
Sorry, I am using guice to inject the class
rus
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

rus
That seems to be the issue to me, that the injection is not working.  Have you tried asserting at the start of your test that store is not null?
Reply | Threaded
Open this post in threaded view
|

Re: Testing database calls in Ratpack

Nick P
You are correct, my store is null when I do an assert at the start.

I have instead created a new instance of the object and when I do the assert it's not null, however with this code I still get the following error

HospitalServiceImplementation store = new HospitalServiceImplementation()

    void "Should save and return a list of hospitals"() {
        given:
        execHarness.yield {
            hospitals.each {
                hospital -> store.save(hospital)
            }
        }

        expect:
        execHarness.yieldSingle {
            store.fetchAll()
        }.value == hospitals
       
    }

Condition not satisfied:

execHarness.yieldSingle { store.fetchAll() }.value == hospitals
|           |                                |     |  |
|           |                                null  |  [[email protected], [email protected], [email protected]]
|           |                                      false
|           ExecResult{complete=false, error=java.lang.NullPointerException: Cannot invoke method rows() on null object, value=null}
[email protected]