How to reset a mock invocation counter using Scalatra, Specs2, Mockito - unit-testing

I never expected that I will need to ask a question on this site because everything is already answered normally but with Scalatra... I haven't find a lot of information so here it is:
I'm not experienced with all that so maybe I'm missing something but from what I understand, if I want to test the API that I develop on Scalatra, I need to start the server everytime I run the test suit, right ?
Second question, how can I reset the invocation counter on a method so I don't have to calculate how many times the method has been called since the beginning of the test suite ? Right now using this give me more than one because it counts the previous test.
there was one(*instance*).*method*(*parameter*)
I can still get around the problem by either counting or putting the test as first test for now but it's not a sustainable solution...
Other thing that I found:
Reset method on the mock... not found
http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#17
Isolating the test in a class scope:
We need to add
val servlet = new Servlet(eventRepoMock)
addServlet(servlet, "/*")
and we can't repeat the addServlet at every initialization
https://etorreborre.github.io/specs2/guide/SPECS2-3.5/org.specs2.guide.Isolation.html
Last thing that I try is:
servlet.repo = mock[EventRepo]
but repo being a value, I can't change it like this.
Neither of these "solutions" feel very clean so I was wondering if someone had a genius idea that can solve that mess !?
Thank you in advance !
EDIT:
Thanks to Eric's comment the above question are solve(that was easy) but now I have problem because I'm testing the get/post which are asynchronous call so resetting the mock does not happen at the right time... Any suggestion ?
Here's a simplified version of the code:
class EventServiceSpec extends ScalatraSpec with Mockito with Before { def is = s2"""
Event Service
GET an existing event
must return status 200 $get_status200
must return the event with id = :id $get_rightEventElement
must call findById once on the event repository $get_findByIdOnRepo
"""
lazy val anEvent = Event(1, "Some Event"
lazy val eventsBaseUrl = "/events"
lazy val existingEventUrl = s"$eventsBaseUrl/${anEvent.id}"
lazy val eventRepoMock = mock[EventRepository]
lazy val servlet = new Servlet(eventRepoMock)
addServlet(servlet, "/*")
def before = {
eventRepoMock.findById(anEvent.id) returns Option(anEvent)
eventRepoMock.findById(unexistingId) returns None
eventRepoMock.save(anEvent) returns Option(anEvent)
}
def get_status200 = get(existingEventUrl){
status must_== 200
}
def get_findByIdOnRepo = get(existingEventUrl){
// TODO count considering previous test... need to find a cleaner way
there was three(eventRepoMock).findById(anEvent.id)
}

All org.mockito.Mockito functions can still be used in a specs2 specification and reset is one of them.
Now, since you are sharing the state of a mock object across several examples, you not only need to reset the mock state before each example but you also need to make your specification sequential:
class EventServiceSpec extends ScalatraSpec with Mockito
with BeforeAll with BeforeEach {
def is = sequential ^ s2"""
Event Service
GET an existing event
must return status 200 $get_status200
must return the event with id = :id $get_rightEventElement
must call findById once on the event repository $get_findByIdOnRepo
"""
lazy val anEvent = Event(1, "Some Event")
lazy val eventsBaseUrl = "/events"
lazy val existingEventUrl = s"$eventsBaseUrl/${anEvent.id}"
lazy val eventRepoMock = mock[EventRepository]
lazy val servlet = new Servlet(eventRepoMock)
def beforeAll = addServlet(servlet, "/*")
def before = {
reset(eventRepoMock)
eventRepoMock.findById(anEvent.id) returns Option(anEvent)
eventRepoMock.findById(unexistingId) returns None
eventRepoMock.save(anEvent) returns Option(anEvent)
}
def get_status200 = get(existingEventUrl){
status must_== 200
}
def get_findByIdOnRepo = get(existingEventUrl){
there was one(eventRepoMock).findById(anEvent.id)
}
}

Related

How to test call twice get method in a spock test framework

I am new to Spock.now I have a twice get Method in the source Java Method, I wrote the code, but always get the NP exception.Anyone can help to see.
def "check call outMethid2"(){
given:
def mockAppointRuleService = Mock(IAppointRuleService)
def mockService = Mock(AppDomainContext)
mockService.getBean(_,_ as Class) >> mockAppointRuleService
def userDTO = new UserDTO(name: "chendd")
mockAppointRuleService.usxx(_) >> userDTO
when:
IAppointRuleService appointRuleService = AppDomainContext.getBean("eh.appointRuleService", IAppointRuleService.class)
def resutl = appointRuleService.usxx()
then:
resutl == userDTO
}
I wish to get the userDTO,but also nullpointeException
From what I see, you should call getBean(...) on mockService rather than on AppDomainContext in when: block. Also, I don't quite understand what is being tested here unless it's a synthetic example. Or you are testing the Spock mocking functionality. In other words, the code (behaviour) under test is missing here

How to mock EntityManager and Query with Spock?

Using spock I need to mock the calls to EntityManager/Query. The line of code I'm trying to mock is:
entityManager.createNativeQuery("nativeQuery").setParameter(1, param1).getResultList()
The mock of entityManager.createNativeQuery returns a null Query object. That then causes a failure because you can't call a method on a null object. And I consequently I can't mock the return of a result set list.
I've tried breaking the statement down into separate ones and accompanying mocks, but that hasn't worked either because I still end up with a null Query.
I don't know if I've got tunnelvision on this right now, or if this can't be mocked - at least with Spock.
All help appreciated!
What you need to do is to build a hierarchy of mocks which will be returning each other, starting with the last one:
Query:
def query = Mock(Query) {
setParameter(_, _) >> it //here as mock itself is returned
getResultList() >> [] //empty list
}
EntityManager:
def manager = Mock(EntityManager) {
createNativeQuery(_) >> query
}
And so on. While what you need to implement is doable it more or less indicates bad design: every time a mock returns a mock a fairy dies, so you should avoid such constructs. What you can do is to separate query building from it's execution - then mocking will be much easier. Sample spec:
def 'fairy has just died'() {
given:
def query = Mock(Query) {
setParameter(_, _) >> it //here as mock itself is returned
getResultList() >> [1] //empty list
}
def manager = Mock(EntityManager) {
createNativeQuery(_) >> query
}
expect:
manager.createNativeQuery("").setParameter(1,1).getResultList() == [1]
}

Grails unit test using grailsApplication

I have a controller that on the save method calls a thread to retrieve some files. The thread has start() in a domain that has this line-
RetrievalThread retrievalThread = grailsApplication.mainContext.getBean ('retrievalThread').
In my unit test I tried this and it worked(I'll keep the other lines omitted that have no bearing right now). Without this line an error occurs saying can't get mainContext on null object,talking about grailsApplication. .
Def mainContext = Mock(ApplicationContext)
MainContext.getBean(_) >>{ name ->
return new MockRetrievalThread()}
The mock thread doesn't do anything.
This test runs fine but, any test after this fail with a null pointer exception with no real information. Looks like a bunch of background grails stuff. Is there a way to clean this up or use something better than what I'm using?
I'm sure there's a way to clean this up in a tearDown, but I think there is a better way.
1.) I would use DI rather than going through grailsApplication.mainContext.getBean; is there a reason you are doing it this way?
class MyController {
def retrievalThread
getFiles() {
return [files: retrievalThread.getFiles(params.id)]
}
}
2.a.) Using DI, you can then just set the controller's retrievalThread to a new instance of MockRetrievalThread within your test.
void "test getFiles"() {
given:
controller.retrievalThread = new MockRetrievalThread()
when:
params.id = 1
def returnedFiles = controller.getFiles()
then:
// assertions
}
2.b.) Or skip the MockRetrievalThread altogether and mock the retrievalThread bean using the mockFor method, and then set the mocked version to the injected instance in your controller.
void "test getFiles"() {
given:
def retrievalThreadMock = mockFor(RetrievalThread)
retrievalThreadMock.demand.getFiles { Integer input ->
return ['file1', 'file2', 'etc.']
}
controller.retrievalThread = retrievalThreadMock.createMock()
when:
params.id = 1
def returnedFiles = controller.getFiles()
then:
// assertions
}
You can use integration testing instead to run the entire app, in order to avoid any beans not being injected.
grails create-integration-test org.bookstore.Book

Issue overriding method using mockFor and MockDomain

I'm trying to unit test a service and I would like to use a mock to override a method on domain object which retrieves a file from a DB.
def mockElem = mockFor(DataElement, false)
mockElem.demand.getFile(){return tempFile}
def dataElem = mockElem.createMock()
dataElem.orderId = "123"
dataElem.id = tempFileName
dataElem.dataType = "cnv"
dataElem.dataStatus = DataStatus.TRANSFERED
mockDomain(DataElement, [dataElem])
When I call a dynamic finder on the data element I want this Mock Domain to be returned with the mockFor demand functionality for getFile. An Assertion error is thrown when the MockDomain line is reached
junit.framework.AssertionFailedError: No call to 'getClass' expected
at this point. Still 1 call(s) to 'getFile' expected. at
groovy.mock.interceptor.StrictExpectation.match(StrictExpectation.groovy:56)
at grails.test.GrailsMock.createMock_closure1(GrailsMock.groovy:136)
at
grails.test.MockUtils.updateMetaClassForClass_closure95(MockUtils.groovy:1297)
at groovy.lang.Closure.call(Closure.java:412) at
groovy.lang.Closure.call(Closure.java:425) at
grails.test.MockUtils.updateMetaClassForClass(MockUtils.groovy:1294)
at grails.test.MockUtils.mockDomain(MockUtils.groovy:470) at
grails.plugin.spock.UnitSpec.mockDomain(UnitSpec.groovy:141) at
com.genospace.inbound.pg.HemeCNVPipelineTestSpec.test processing Heme
file(HemeCNVPipelineTestSpec.groovy:66)
Not sure what is the question.
You got this error because you are mocking an object twice :
with mockFor/createMock
with mockDomain
mockDomain need to know some information about objects being passedas arguments (here it verifies the class is correct) but mockFor did not allow that getClass() was called : you did not add a demand for such call.
Do you really need to mock with demand ?
I think the simple case should work :
def dataElem = new DataElement()
dataElem.orderId = "123"
dataElem.id = tempFileName
dataElem.dataType = "cnv"
dataElem.dataStatus = DataStatus.TRANSFERED
dataElem.file = tempFile
mockDomain(DataElement, [dataElem])

How can I unit test grails service which is using methods from a plugin?

I've got a service, which is using sendJMSMessage method which is provided by jms-grails plugin.
I want to write some unit tests, but I'm not sure how to "mock" this method, so it just does nothing at all.
Any tips?
You can metaClass the method to have it return whatever you want.
#Test
void pluginCode() {
def myService = new MyService()
def wasCalled = false
myService.metaClass.sendJMSMessage = {String message ->
//I like to have an assert in here to test what's being passed in so I can ensure wiring is correct
wasCalled = true
null //this is what the method will now return
}
def results = myService.myServiceMethodThatCallsPlugin()
assert wasCalled
}
I like to have a wasCalled flag when I'm returning null from a metaClassed method because I don't particularly like asserting that the response is null because it doesn't really assure that you're wired up correctly. If you're returning something kind of unique though you can do without the wasCalled flag.
In the above example I used 1 String parameter but you can metaClass out any number/type of parameters to match what actually happens.