I am currently trying to use spock instead of junit in my unit tests.
But I ran into problem of MissingMethodInvocationException.
I am mocking Provider<T>.get(), like below
Provider<SomeOjb> a = Mock()
def setup(){
SomeOjb obj = new SomeObj();
Mockito.when(a.get()).thenReturn(obj)
}
but after running it I am getting
org.mockito.exceptions.misusing.MissingMethodInvocationException
when() requires as argument which has to be 'a method call on a mock'
I tried two diffrent approach, one of them is to create mock as
def a = Mock(Provider<SomeObj>) but in this case I getting syntax error after running, issue is with <>
And the last idea was to just use annotation
#Mock
Provider<SomeObj> a;
and use when/then as before, and in this case it worked alright.
Any idea why firt idea is not correct?
Obviously I am stupid.
Issue was because I used Mockito api. Not spock mock api.
It should looks like:
Provider<SomeOjb> a = Mock()
def setup(){
SomeOjb obj = new SomeObj();
a.get() >> obj
}
Related
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
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
In my unit test, I mock a service (which is a ref of the class under test).
Like:
given:
def mockXxService = mockFor(XxService)
mockXxService.demand.xxx(1) {->}
service.xxService = mockXxService
when:
service.yyy()
then:
// verify mockXxService's xxx method is invoked.
For my unit test, I want to verify that mockXxService.xxx() is called. But grails document's mockControl.verify() doesn't work for me. Not sure how to use it correctly.
It is very similar to mockito's verify method.
Anyone knows it?
You are using spock for your unit test, you should be easily able to use spock's MockingApi check invocations:
given:
def mockXxService = Mock(XxService)
service.xxService = mockXxService
when:
service.yyy()
then:
1 * mockXxService.xxx(_) //assert xxx() is called once
You could get more insight about mocking from spockframework docs.
You can even stub and mock that while mocking the concerned service as:
def mockXxService = Mock(XxService) {
1 * xxx(_)
}
If you want Mockito-like behavior in Grails unit tests - just use Mockito. It is far more convenient than Grails' mocking methods.
In one of my unit tests, I am having some difficulty getting a mocked method to executed. I have the following test code:
void testExample() {
def mockICFService = new MockFor(ICFService)
...
//Mock the methods
controller.metaClass.icfList = { def person ->
println "icfList"
return [new IC(conceptId:'12345')]
}
mockICFService.demand.getAllIC(1..1) { def id, def withHist, def appId ->
println "mocking service"
return new Person()
}
...
def model = controller.detail()
}
Inside of detail in my controller class I create a Person via the ICFService's getAllIC(). This part works correctly. Later in the function, however, there is a call to icfList (which is defined in the controller). Through println's I have determined that the call is still being made, although it is returning an empty array. I believe that this is because the array is populated based on data in the servletContext, but in Unit Testing there is no access to that (hence my trying to mock it out).
Does anyone know how to force the test to use the mocked version of controller.icfList instead of calling the actual method in controller?
When I try your code, what blows up for me is the mocked service, and the part that works properly is the mocked-out icfList() method. The opposite of your observation, interestingly. For what it's worth, here's what I did:
First replace new MockFor() class instantiation with the mockFor() method. Then you need to inject the mock service into the controller.
def mockICFService = mockFor(ICFService)
controller.iCFService = mockICFService.createMock()
By doing the above, only the mocked versions of icfList() and getAllIC() get called, so you are not using the servletContext at all. Check out the Grails testing documentation for more info.
I want to test a Grails controller which calls a service. I'd like to mock the service. The Service has a method:
JobIF JobServiceIF.getJob(int)
and JobIF has a method:
String JobIF.getTitle()
Here's my controller
def workActivities = {
JobIF job = jobService.getJob(params.id)
[career:job]
}
I understand that I need to mock the service and the job class (there are concrete implementations for both) but I'm struggling to get my head around the Groovy mocking object syntax. How do I mock a job and set the title to something, say "Architect" and then test the code?
So far I have:
void testWorkActivities() {
def controller = new CareersController()
... // Mocking stuff I don't know how to do
controller.params.id = 12
def model = controller.workActivities()
assertEquals "Architect", model["career"].getTitle()
}
You basically have two choices
Use the Groovy mocking classes, i.e. MockFor and StubFor
Use the Grails mock classes by calling the mockFor method of GrailsUnitTestCase. The class returned by this method is an instance of GrailsMock
Personally, I have found the Groovy mock objects to a bit more reliable than the Grails mocks. On occasions, I've found that my Grails mock objects were bypassed, even though I appeared to be setting everything up correctly.
Here's an example of how to use the Groovy mocks:
void testCreateSuccess() {
def controller = new CareersController()
// Create a mock for the JobService implementation class
def mockJobServiceFactory = new MockFor(JobService)
mockJobServiceFactory.demand.getJob {def id ->
// Return the instance of JobIF that is used when the mock is invoked
return new Job(title: "architect")
}
// Set the controller to use the mock service
controller.jobService = mockJobServiceFactory.proxyInstance()
// Do the test
controller.params.id = 12
def model = controller.workActivities()
assertEquals "Architect", model["career"].getTitle()
}
The process is basically the same when using the Grails mocks, but you call the mockFor method of the test class, instead of instantiating MockFor.