Grails unit test verify mock method called - unit-testing

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.

Related

Mock is giving missing method exception in spock framewrok

I am running my Junit test cases for my groovy class using spock framework I am using Mock to invoke my class. but it is giving me MissingMethodException but if I invoke the same method by normal creating object def obj = new MyClass() way it is working. please let me know am I missing something? below is my stacktrace
Expected no exception to be thrown, but got 'groovy.lang.MissingMethodException'
at spock.lang.Specification.noExceptionThrown(Specification.java:119)
at .AsplTest.fetchXmlTest(AsplTest.groovy:35)
Caused by: groovy.lang.MissingMethodException: No signature of method: com.webservice.Service.fetchAsplXml() is applicable for argument types: (java.lang.String, groovy.net.xmlrpc.XMLRPCServerProxy, java.lang.String) values: [3c98fa0dd1b5d92af599779bfb7be655, groovy.net.xmlrpc.XMLRPCServerProxy#797b0699, ...]
Possible solutions: getFetchAsplXml()
at .AsplTest.fetchXmlTest(AsplTest.groovy:33)
below is my test code
public void fetchXmlTest() {
given:
def asplObject=Mock(Service);
when:
asplObject.fetchXml(sessionId, serverProxy, "https://serverproxy")
then:
noExceptionThrown()
}
FYI:
my groovy version is 2.4.12 and spock version 1.1-groovy-2.4
It seems to me that you are doing things backwards.
Mocks are not test subjects. They are used to control the interactions of your test subjects with other objects. It looks, from the code you posted, that you want to test the invocation of method fetchXml on your Service object.
To do this, you need to create an instance of Service, and call the method. If your Service has collaborating objects, then you can Mock them, and add interactions, like this:
given:
def service = new Service()
and:
service.collaboratingObject = Mock(CollaboratingObjectClass)
when:
service.getFetchAsplXml()
then:
1 * service.collaboratingObject.someMethodReturningAString(_ as String) >> {String input-> "mockedResult from $input" as String }

Unit test grails with domain objects using GORM functions

I have the following piece of code inside a service class named OrderService in Groovy on Grails. I want to make a unit test for this class. User and Order are domain classed. A user has many orders.
boolean testfun(long userId, lond orderId){
User user = User.findByUserId(userId)
if(user == null)return false
Order order = Order.findByUserAndId(user, orderId)
if(order == null)return false
return true
}
The unit test that I am trying to write is the following (using Spock):
#TestFor(OrderService)
#Mock([User, Order])
class OrderServiceSpec extends Specification{
def "test funtest"() {
User user = new User(2)
Order order = new Order()
order.metaClass.id = 3// I want to assign the id of the order in domain
order.save()
user.addToOrders(order)
user.save()
expect:
service.testfun(2,3) == true
}
}
However this test fails because the order is null. Can anyone help me?
Another question is: is this test a unit test? or should I write an integration test in grails?
It depends on what you're actually trying to test, but this can be a unit test—I'd just recommend modifying it a little bit to isolate only the service method that you're interested in testing. You're not looking to test the domain classes at all, so it's best to mock/stub the behavior that you need from them to test the service functionality.
A good way to do this is with Spock's support for interaction based testing via mock objects. Basically we specify that when the service's testfun() method is called, we expect User.findById() to be called once and Order.findByUserAndId() to be called once as well. Spock then allows us to stub out each method call so that we specify what we want the method to return. When we run the test, the stub will be used, not the actual GORM method.
Some complexity lies with stubbing out static methods (like GORM methods), but you can use a GroovySpy to get the job done.
Also, I'm assuming you meant to use User.findById() instead of User.findByUserId()?
Something along these lines should work for you:
def "test funtest"() {
setup:
// Global so that it replaces all instances/references of the
// mocked type for the duration of the feature method.
GroovySpy(User, global: true)
GroovySpy(Order, global: true)
when:
def result = service.testfun(2,3)
then:
// No need to return real objects, so use a mock
1 * User.findById(2) >> Mock(User)
1 * Order.findByUserAndId(_ as User, 3) >> Mock(Order)
result == true
when:
result = service.testfun(2,3)
then:
1 * User.findById(2) >> null
result == false
}
Note that we've isolated the service method. Any collaborating objects (User and Order) are only being interacted with via stubs and we can test the functionality of the service method without worrying about GORM at all.

Grails Spring Security Testing

I use the Grails Spring Security Plugin for my project and now want to unit test my code. I have the following code in my controller:
def index() {
redirect action: 'show', params: [id: springSecurityService.currentUser.id]
}
My Test Class has the following code:
void testIndex() {
controller.index()
assert "/user/list" == response.redirectedUrl
}
This test fails:
| Running 8 unit tests... 1 of 8
| Failure: testIndex(xxx.UserControllerTests)
| java.lang.NullPointerException: Cannot get property 'currentUser' on null object
at xxx.UserController.index(UserController.groovy:12)
at xxx.UserControllerTests.testIndex(UserControllerTests.groovy:19)
How can I authenticate a spring security user in a test case? How would you write the unit test?
You have to use functional tests for security. Unit tests use mocking but don't have plugins available, or a real request. Spring Security is implemented with a filter chain, so you need a real running server. If you use mocks, you're just testing the mocking.
For something this simple I wouldn't bother with complicated mocks, a straightforward
controller.springSecurityService = [currentUser:[id:1]]
would be sufficient.
It appears that your reference to springSecurityService is null. As long as you have a field in your controller named springSecurityService, it should be injected. Are you using it as a local variable only in your index method and did not declare it as a field?
My UserController is as follows:
class UserController {
/**
* Dependency injection for the springSecurityService.
*/
def springSecurityService
....
}
UPDATE
Based on your comments to this answer, you did declare a springSecurityService field in your controller. I took my working application and tried a test that mirrors yours with my controller method:
#TestFor(UserController)
class UserControllerTests {
void testSomething() {
controller.register()
}
}
I got a NullPointerException as well. From Burt's answer, (I did not know this), I think the springSecurityService instance is null in the contexts of the Unit Test execution.

Mock a method for Grails Unit Test

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.

Grails unit testing help needed

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.