how to mock a class inside a controller? - grails

I have a controller method which inside it creates a domain instance and saves it. I need to simulate that this save fails so i am thinking of mocking this domain and for save method i throw an exception. Is there a way to mock the donor class.
def method(){
...
Donor donor = new Donor()
donor.properties = convertedParams
donor.save(failOnError: true)
...
}
I know how to mock a service that is used inside a controller
def mock = new groovy.mock.interceptor.MockFor(ExampleService)
def exampleService = controller.exampleService
mock.demand.exampleMethod(){ Long id, TransactionResponse tr ->
throw new RegistrationActivationException(new IllegalStateException('something went wrong'), [])
}
mock.use{
controller.exampleService = new ExampleService()
model = controller.exampleMethod()
}
So, the code above will mock out the ExampleService service used in the controller. Is there a way to do mocks like that but not for a service but for a domain that is instantiated inside a method like in the first code block above. I need to mock out the Donor class and when save is called then i need to throw an exception in order to simulate and test what happens when the donor save fails.
I appreciate any help! Thanks!

I need to mock out the Donor class and when save is called then i need to throw an exception in order to simulate and test what happens when the donor save fails.
This seems like a very convoluted way to achieve an exception being thrown on save. Instead, it seems you could just try to save an instance of Donor that doesn't match it's constraints. Assuming Donor has at least one property that is not null, this should achieve the same thing
new Donor().save(failOnError: true)

Related

Grails Controller integration test executes actions of the parent, RestfulController class

I have a weird problem with integration testing restful controllers... In the following code snippet, when I make a post request from tests, the save method of the parent, RestfulController class is called instead of the save method of the child class, MyController and because they have different signatures, this ends up resulting in a UNPROCESSIBLE_ENTITY response.
class MyController extends RestfulController<MyDomain> {
static responseFormats = ['json', 'xml', 'hal']
MyController() {
super(MyDomain)
}
def save(MyCommand command) {
...
}
}
When I run the following test, the save() action of my controller's parent class, RestfulController gets executed, thus leading to UNPROCESSIBLE_ENTITY response, since I am using a Command object which is different from my domain class.
void "Test the save action correctly persists an instance"() {
when: "The save action is executed with valid data"
response = restBuilder.post(resourcePath) {
accept('application/json')
header('Authorization', "Bearer ${accessToken}")
json validJson
}
then: "The response is correct"
response.status == CREATED.value()
response.json.id
Vote.count() == 1
}
What can I do to fix this, please?
Overloading controller actions is not supported. You can override them, but you can't overload them.
What is happening is the framework is invoking the no-arg save() action in the parent class, which never invokes your method (nor should it).
You can rename your save(MyCommand command) so it doesn't have the same name as an action in your parent class and then provide a corresponding URL mapping and you will be on your way. Depending on what you want to do in the action, that may or may not be the best thing, but that is 1 path you can take.
I hope that makes sense.

Grails - Pass data from view to controller

I'm trying to pass Param data from view to controller and I'm having trouble. Here's what I'm currently trying to do.
View:
<form action="${doStuffURL}" method='post' params="[keyId: ${mykey.id[i]}]"><g:actionSubmit value="doStuff"/></form>
Controller:
def myObjectService //inject service object
def doStuff = {
myObjectService.doStuff("${params.keyId}") //this blows up because it's value of NULL
myObjectService.doStuff(8) //this works fine
}
It gets to the method block because the error log says "no signature of method MyObject.doStuff() is applicable for argument types: values: [null]." Also, I'm able to see ${mykey.id[i]} data from another field, so the data is definitely in the view.
How can I get the controller to read the Param data?
Thanks!
err lots wrong here:
<form action="${doStuffURL}" method='post' params="[keyId: ${mykey.id[i]}]"><g:actionSubmit value="doStuff"/></form>
why not use:
<g:form name="something" controller="yourController" action="youraction">
As you can see above you are having to generate
form url (maybe you have your reasons)
Controller:
def doStuff = {
MyObject.doStuff("${params.keyId}")
}
Differences between action and methods in Grails controllers
So firstly why you should change controller but my actual concern here is
MyObject.doStuff
is MyObject.doStuff a static method ?
since that is only when a call like this would work. The link shows a static method. gets called here and it may confuse you due to it calling it via executor.registerSenderFault due to how it is generated working - expandability - for future classes that do same thing. this could have been EmailExecutor.registerSenderFault which is the full class in uppercase like you have declared.
surely it should be a service notice starting with lower case.
myObjectServive.doStuff(stuff)
If above is some real method in MyObject and is not a static method then you need to instantiate the class
MyObject myObject = new MyObject()
myObject.doStuff(stuff)
but in short this is why services exist it is all there to save you all the hassle since they just get injected.
I suggest you do some reading looking around
E2A
def doStuff = {
println "my params are $params "
//do you see keyId in there ?
//if so what is doStuff expecting as input a string ?:
// since if you do
println "${params.keyId.getClass()}"
//by default it will be a string you may need to change it from:
//myObjectService.doStuff("${params.keyId}")
myObjectService.doStuff(params.keyId as Long)
}
Personally I don't think it is any of the above edited comments, it still relates to how/what you are injecting. I have seen similar issues. I would suggest you create a brand new service and inject new service as a test and start again - not convinced you were injecting it correctly or if you are the service may be some abstract class rather than a normal service. Or.... you are making some form of similar mistake in the uppercase/lowercase declaration of the service name so you may have created:
MyObjectnameService and calling it using myObjectNameService difference in N in those or.... even worse you have created actual service as myObjectNameService with lowercase name.
test this all again using a much simpler naming convention and create a new service as a test
grails create service MyService
and try again using this service

Grails controller test making assertions about model when rendering a template?

Using Grails 2.1.0
It seems that doing this from a controller:
render(view: "someView", model: [modelEntry: "hello"])
allows me to do this in a unit test for that controller:
controller.method()
assert model.modelEntry == "hello"
However, if I change the controller to do this:
render(template: "someTemplate", model: [modelEntry: "hello"])
Now the model instance in the test is an empty array. I've done quite a bit of searching about this, and most of the solutions seem to be for Grails 1, often involving the modelAndView object (which doesn't exist in my test) or renderArgs (ditto).
The only solution I've found is to manually override the views within the test, like this:
views['_someTemplate.gsp'] = '${modelEntry}'
and then making assertions about the string. But I dislike this solution because it:
requires the test knows the filename of the template
makes it difficult to test model entries that don't have good toString() methods
makes it difficult to make multiple assertions about related model entries.
Is there any way to more directly get at the entries in the model from a test case when the controller renders a template?
Digging a little bit in the code of the render method (org.codehaus.groovy.grails.web.metaclass.RenderDynamicMethod) I can see that the modelAndView is setted only when you render a view.
Rendering a template will return a null modelAndView indeed.
To inspect the model in this case I think you can use the Groovy metaClass. The idea is to intercept the original method, store the value and then call him.
Based on this question, I builded this (not tested, may need adjusts):
#TestFor(MyController)
class MyControllerTests
def templateModel
#Test
void inspectTemplateModel() {
def originalMethod = MyController.metaClass.getMetaMethod('render', [Map] as Class[])
controller.metaClass.render = { Map args ->
templateModel = args.model
originalMethod.invoke(delegate, args)
}
controller.method()
assert templateModel.modelEntry == 'foo'
}

Groovy metaprogramming

In a Service of a Grails project, I like to find, at run time, the arguments of Dynamic Methods in order to inform callers.
Also, I like to call the method and if doesn't exist to return an error,
I will appeciate any help.
You can configure URLMappings in grails to get the value of the dynamic method and call it against your object for example you can do the following
In your urlMappings.groovy define a mapping with two embedded variables object and method
"/$object/$method" (controller:"api",action:"invoke")
Define a 'api' controller with an invoke action. See code below with the logic on how to invoke the method on the object
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
class ApiController {
def invoke = {
def object = params.object
def method = params.method
def args
if(object) {
def domainClass = AH.application.domainClasses.find{it.name == method}?.clazz
if(domainClass.metaClass.getStaticMetaMethod(method,args)) {
domainClass.metaClass.invokeStaticMethod(target,input.method,args)
}
}
}
}
In my example, I assumed that you're calling a static dynamic finder on the domain class. You can generalize this to handle instance methods as well. You need however to provide more information such as the object id, in your request to load the object and call the method against it.
"/$object/$id/$method" (controller:"api",action:"invoke")
-Ken
Not sure I understand your question, but the last part about checking if you can call a method on an object, this can be done by checking the meta class of the object you are dealing with like this.
obj.metaClass.respondsTo(obj, 'theMethodYouWantToCall')
obj is the object you want to call the method on, and theMethodYouWantToCall is the name of the method you want to call.
respondsTo will return an empty list [] if the method you are trying to call is not found

The sequence of ModelDriven and Prepare?

I put the println() in each method of Action class.
public String execute() throws Exception {
System.out.println("execute");
//...
}
public void prepare() throws Exception {
System.out.println("prepare");
//...
}
public Object getModel() {
System.out.print("getModel");
//...
}
I thought the order would be;
prepare → execute → getModel.
Because I remember I read it in the book, so I used to construct beans class and do some logics in prepare(), and just return SUCCESS in execute().
And I think getModel is for pushing the bean to the valueStack, right?
...anyway the console showed me this. It's very weird;
prepare → getModel → execute.
And this is becoming a huge problem to me. It's very hard to explain the reason in English... but I'll try!
I used to create each action class which is dealing with same beans, and of course there are same codes(variables, and their getters and setters) duplicated in each action class.
Now I'm trying to create one action to avoid that duplication. This action class has several methods(mapped in struts.xml like this;<action name="View_board" method="view">).
And as we saw in the console, this view() is called at the last in the action class like execute(). The prepare() does only construct beans, and the view() does real jobs. But getModel() is called before calling of view(), so there's no chance to put the beans to ValueStack.
I hope you guys understand what I'm trying to explain.
To sum it up, there are each action class like BoardView, BoardDelete, BoardWrite... and they worked well! But I hate that duplicated things so I created BoardManager class. This class has each method(like view()) which was handled by class(like BoardView). But this view() was called after the call of getModel(), so the bean(return of getModel()) has no chance to be pushed to the ValueStack.
Please help me out. Teach me your know-how in the field. I'm developing it all on my own and this is making me feel so hard.
Thank you!!
You have to set the Model object yourself as the modeldriven interceptor can only push it to the stack if its not null. If your getModel() looks like this:
SomeModelClass myModelObject = null;
public Object getModel()
{
return myModelObject;
}
... you'll have to set the modelObject so it can get pushed to the valueStack. You could do it this way I guess:
public void prepare(){
myModelObject = new myModelObject("I'm so new");
}
... or just initialize it in the field:
SomeModelClass myModelObject = new myModelObject("I'm so new");
Don't forget to implement the appropriate Interfaces (ModelDriven and Preparable). Hope this helps a bit.
I found my own solution.. but not a good one..
When setting domain object by setter, I push it to the valuestack manually..
It works good and only 2 lines added to my class.
But I don't feel that good.

Resources