Integration Tests in grails: getting null in query string parameter - grails

I'm doing integration tests for controllers in grails.I need to pass query string in test case and I'm passing it as controller.request.queryString for the same.
My tests is getting failed. It's giving me null value for the query String parameter.
Controller - UserExController
Foll is the action on which i'm doing integration testing.In this I'm reading query string parameter 'uid' and getting the userInstance using GORM method
def getUser() {
//reading the query string parameter 'uid'
def userId = request.getParameter("uid")
User user = User.findByUsername(userId)
render view:'edit', model:[userInstance:user]
}
This is the test for the above written action .In this I'm passing the query string parameter and calling the action
class UserInstanceTests extends GroovyTestCase {
#Test
void testPerfSummaryApi() {
def userExController=new UserExController()
userExController.request.queryString='uid=rp123'
userExController.getUser()
def model = userExController.modelAndView.model.userInstance
assertNotNull model
}
}
I'm getting groovy.lang.MissingMethod.Exception in the foll call:
User.findByUsername(userId) //userId is comming null

Change in Controller:
def userId = request.getParameter("uid")
to
def userId = params.uid
Change in int test:
userExController.request.queryString='uid=rp123'
to
userExController.params.uid='rp123'
Grails' dynamic binding helps in binding the query parameters to params and request to request in the controller.

This should make things work for you (tested on Grails 2.0.4):
userExController.request.addParameter('uid', 'rp123')
However, I would recommend to turn to dmahapatro's suggestion and refactor your controller to use params.uid instead of request.getParameter("uid"). Or even introduce a command object. The way you are doing it now just does not seem to be the standard Grails way.

Related

Private Method for Nested Resource

From Previous:
Rails 4 Nested Resources/Routes... almost there...?
My private method within my lines controller to load the manufacturer into the controller is throwing an error...
I use before_filter :load_manufacturer
and the function is:
def load_manufacturer
#manufacturer = Manufacturer.find(params[:manufacturer_id])
end
When I try to edit the line instance in the form, I get:
Couldn't find Manufacturer with id=manufacturer_id
But it is passing the manufcaturer params ok...
Parameters:
{"manufacturer_id"=>"manufacturer_id",
"id"=>"17"}
Your manufacturer id is incorrectly set. Its set to string "manufacturer_id" instead of an integer id value(in String format). The problem lies else where. As you can see
{"manufacturer_id"=>"manufacturer_id"
Should look something like
{"manufacturer_id"=>"1"
manufacturer_id should be an integer value

Fetch label of property in Grails domain

How do I fetch the label property of a domain from messages.properties. For example, I have a domain as following
class Books{
String name
String author
String description
String rating
}
And in message.properties I have the following
Books.name.label=Title
Books.author.label=Author
Books.description.label=Description
Books.rating.label=Rating
So can I do something like
def fieldName = Books.name.label
and get 'Title' ? Is there any way to do this ?
If you're in a Controller or Service, you can inject the bean
def messageSource
and then you can call:
messageSource.getMessage(code, args, defaultMsg, locale)

How to access property from grails query

I have a domain class called Application as follows:
class Application {
static hasOne = [resumption:Resumption, employee:Employee]
//Employee employee
Date startDate
Date endDate
Integer amountOfDays
String leaveRecommended
String leaveNotRecommended
Date supervisorDate
String toString(){
return "Application for ${employee.lastName}, ${employee.firstName}"
}
}
In the ApplicationController I'm trying to write a query that is going to find all applications that match a particular employee id. I do so as follows:
def applicationlist(){
if(!params.max){
params.max = 10
}
def query
def criteria = Application.createCriteria()
def results
query = { eq("employee_id", Long.parseLong("1")) }
results = criteria.list(params, query)
render(view:"employeeapplicationlist", model:[applicationlist:results])
}
Now I keep getting the error: "could not resolve property: employee_id"
I've checked the generated Application table in MySql, there is a column called employee_id with a value. The weird thing is I can access any other property (like amountOfDays), so what's the deal with employee_id? Why is it complaining that it cannot resolve the property? What am I missing? Thanks in advance.
Associations in the criteria DSL are of the form
Application.withCriteria{
employee{
eq 'id', 1
}
}
http://grails.org/doc/latest/guide/GORM.html#criteria
But you could probably just do:
def employee = Employee.proxy(1)
Application.findAllByEmployee( employee )
This appears a few times in the Grails User Guide as 'querying associations'
Oh well it looks like I'm still not fully adjusted to interfacing with the database on an Object level. For anyone else with this or a similar problem, here's the fix:
query = { eq("employee.id", Long.parseLong("1")) }
Sine the Application Domain class has one Employee, then we just need to access the id field of that employee. Remember we're in the ApplicationController.

grails redirect error

problem with redirection in a grails in a controller.
in Controller:
def function1 = {
... do stuff ...
... go to service ...
redirect(action: "searchName", name: test)
//redirect(action: "searchName", params: [ name: test ])
}
in searchName, there are no parameters. its an empty list.
try the second way of calling the redirect and i get grails exceions (MissingMethodException), for a method that does exist.
there is nothing special that i can see, that is going on.
any help?
EDIT
the MissingMethodException is not on the searchName function, but on a method within the service. this method is there.
if i use the first redirect method, then the service method works correctly, but the redirect to searchName contains empty parameters.
if i switch the redirect method, then the service method no longer works
(with the exception, so it never gets to the redirect). with fully recompiled/cleaned code.
also, searchName is a closure. again, nothing fancy.
grab the name parameter, and work with it.
class MyWierdController {
def function1 = {
... do stuff ...
... go to service ...
String test="blah"
redirect(action: "searchName", name: test)
}
def searchName = {
if (params.name) {
log.info "its there"
} else {
log.info "its not there"
}
}
}
redirect() is a real HTTP redirect. You will have issues, because all your params will be serialized an deserialized and probably you are losing type information (e.g. Date, which will be string after the redirect.
The first version will ignore name parameter, since all parameters have to be within params.
Try
redirect(action: "searchName", params: ["name": "test"]);
// or
redirect(action: "searchName", params: params);
Since you did not quoted the parameters, groovy expects them to be a variable and tries to resolve them. Since both are undefined it is becoming params: [null: null].
However I guess, that you are searching for render(view: "searchName", params: ["name": "test"]), which will not do a HTTP redirect.

Unit testing controller actions with complex viewModels

I'm just getting going with ASP.NET MVC and I'm also new to unit testing :) So far, so good.
I have a controller action that sets up an index view using a viewmodel. Testing the controller action is straight-forward as I can pass a fake service class in the controller's constructor, but my viewmodel is quite complex and fetches it's own service class on instantiation.
Code should make this clearer I hope...
Controller action:
Function Index(ByVal id As Integer?) As ActionResult
Dim totalCount As Integer = 0
Dim selectedClient As Integer
If id Is Nothing Then
selectedClient = _portalClientService.GetFirstClient().ID
Else
selectedClient = id
End If
Dim users As MembershipUserCollection = _membershipService.GetUsersByClientId(selectedClient, 0, 1000, totalCount)
Return View(New UserListViewModel(users, selectedClient))
End Function
Viewmodel class:
Public Class UserListViewModel
Private _clientService As IPortalClientService
Public Sub New(ByVal users As MembershipUserCollection, ByVal selectedClient As Integer)
Me.New(users, selectedClient, Nothing)
End Sub
Public Sub New(ByVal users As MembershipUserCollection, ByVal selectedClient As Integer, ByVal clientService As IPortalClientService)
_users = users
_clientService = If(clientService, New PortalClientService)
_clients = New SelectList(_clientService.GetClients.OrderBy(Function(c) c.ClientName), "ID", "ClientName", selectedClient)
End Sub
Private _users As MembershipUserCollection
Public Property Users() As MembershipUserCollection
Get
Return _users
End Get
Set(ByVal value As MembershipUserCollection)
_users = value
End Set
End Property
Private _clients As SelectList
Public Property Clients() As SelectList
Get
Return _clients
End Get
Set(ByVal value As SelectList)
_clients = value
End Set
End Property
End Class
EDIT:
When testing the controller action, how do I get the viewmodel to use a fake service class?
Should I just ditch the first constructor and always pass in the service from the controller or is there another way?
Cheers,
Nick
I am probably splitting hair, but I would say your model is more a domain model than a view model. Remove the dependency to the IPortalClientService, or at least do not let the model instantiate it by itself.
I prefer to remove such dependencies away from the view, and over to the controller.
Actually, this is a pattern that we use all the time in our public facing API's, and demonstrates good use of dependency injection. I would pass this in a code review with no problems.
Your implementation gives the user the option to flexibly create the object, and provides for testability.
The only "problem" is that your tests can't easily cover the one line of code in the first constructor, but that's only a problem if you have someone who's fanatical about code coverage - which is usually a problem in itself.

Resources