I am trying to get unit testing to work for scaffolding. There are a few changes that I made to the original scaffolding template to serve what I needed for my application. This is the code for the test:
void "Test that the show action returns the correct model"() {
when:"A domain instance is passed to the show action"
populateValidParams(params)
def domainName = new DomainName(params)
controller.show(domain.toString())
then:"A model is populated containing the domain instance"
model.domainNameInstance == domainName
}
This is the code for the show action, where I grab the domain instance from the database based on two values within the id, which is created by a toString method within the controller:
def show(String id){
if (id!=null){
def (term, college)=id.split('_')
DomainName domainNameInstance
respond domainNameInstance=DomainName.findByVal1AndVal2(val1, val2)
}else{
response.sendError(HttpServletResponse.SC_NOT_FOUND)
}
}
The issue that I am having is that when I run the test, the domainInstance is null within the test, whereas the domain is returning the right values. Would someone know what I need to change to make the domainInstance inside the test not null? For reference, I am using Grails 2.4.3 and the Scaffolding 2.1.2 plugin.
In your unit test, you need to save the DomainName instance you are creating. Your show action is querying the database but you haven't persisted the test instance.
Related
I'm new to unit testing and I've been trying to test a GET method of the card game that I've built.
My TestCase is the following:
def test_rooms(self):
c = APIClient()
room_id = PokerRoom.objects.get(name='planning').id
request = c.get('http://127.0.0.1:8000/room/{}'.format(room_id))
print(request)
The id is a UUID that's why I'm using the room_id method.
My url:
path('room/<int:pk>', room),
where room is a #api_view(['GET']) method and pk is the id of the room. But when I try to test it, an error occurs:
<HttpResponseNotFound status_code=404, "text/html">
Checked if the room exists in the test database and it exists, now I don't know what is happening. Can someone help me?
Can you add more details to your code above, such as how the test suite has been created, how is the data set up, etc? One problem I am noticing straight away is how the request is being made. Why are you using a complete URL? If you are using the Django/DRF test API client, you should use the view path URL instead of the complete URL.
Reference: https://docs.djangoproject.com/en/4.0/topics/testing/tools/#overview-and-a-quick-example
I'd like to run a parametrized test in Spock using the #WithMockUser with a different role per each iteration.
As an example, the following test code shows no compilation error and is run twice.
But the result fails, since the #role is resolved only in the #Unroll, but not in the #WithMockUser annotation.
#Unroll("#role is authorized to get admin")
#WithMockUser(username = "user", roles = ["#role"])
def "User is authorized to get admin"() {
when:
def adminDto = adminController.getAdmin()
then:
adminDto.getStatusCode() == HttpStatus.OK
where:
role << ["USER", "ADMIN"]
}
So my question is: Is it possible to run such a test as a parametrized one?
Thank you in advance!
Note: I'm aware the annotation could look like:
#WithMockUser(username = "user", roles = ["USER", "ADMIN"])
but this would be a different behavior - one call with both roles.
Short answer no.
The annotations are statically compiled at compile time and cannot be modified by Spock, the iterations are generated/evaluated dynamically at runtime.
The #Unroll annotation has some special support for data variables to make it work, while the Spring annotation doesn't know anything about Spock.
You could look at WithMockUserSecurityContextFactory and use that to manually set the the SecurityContext in the given block.
Attempting to unit test a Grails 2.1.x controller that calls a template to show a list of history items with a status. This controller works fine in manual testing but were attempting to automate things and I'm getting stuck on this part. Part of our issue may be that the domain object is over engineered.
The setup for this test may be more integration rather than unit testing but I'm not sure I can test the function with out it.
The controller action generates a list of history items via a createCriteria query. This list is passed to the template to be rendered.
def loadHistValues(){
def histDomainObject = new historyDom()
def elements = histDomainObject.createCriteria().list(max: params.max, offset: params.offset)
render (template: 'searchResults', model:[elements: elements]
}
The template has code that iterates through the list putting values in each column. One of these items is getStatus(). This calls a utility service to return the values.
def getStatus(){
return historyUtillityService.getStatus(this)
}
The service gets the latest history event and returns the value.
def getStatus(HistoryDom hist){
def histStatus = HistoryEvent.createCriteria().get(
maxResults(1)
order('id', 'desc')
eq('historyDom', hist)
)
if (histStatus == null)
return 0
else
return histStatus.status
}
I'm getting a null pointer when the getStatus() is called.
I've setup both mock domain object and mock services but I'm not sure that these are getting down to this level or maybe I'm calling them wrong.
#TestFor (HistoryController)
#MockFor (HistoryDom, HistoryEventDom)
class HistoryControllerTests{
def util = new UnitTestUtil()
void testLoadHistValues(){
def mockHistoryUtilityService = mockfor (HistoryUtilityService)
mockHisotryUtilityService.demand.getStatus (-> return Status.QUEUED)
def histObj1 = util.initMockHistObj(1)
def histObj2 = util.initMockHistObj(2)
histObj1.save()
histObj2.save()
def mockHistEvent = new HistEvent(
histDate: histObj1.getHistDate(),
histObj: histObj1,
histStatus: Status.QUEUED
)
mockHistEvent.save()
controller.loadHistValues()
assert response.text contains("Something worth testing")
}
I tried setting a mock view before the call to the controller and checking the response text for that but it never gets past the call to the controller since its still trying to process the template. I'm at a loss at this point as to how to test this controller function, or is it that the object wasn’t architected properly; this seems a bit overly complicated.
answer was to mock things for constrainsts tests before they would get fully saved by mock GORM. I guess mockForConstraintsTests dosnt quite function as I expected
This is my first application using backbone and REST API, I'm a bit confused with some specific scenarios when it comes to creating-editing. So if the model exits on server, it will EDIT, if it doesn't it CREATES.
When I pass on a unique identifier in my model, it knows it exits, but if I pass a combination of existing data without a unique identifier it always assumes it should CREATE. I'm not sure if this should be solved on client side or server.
For instance:
var exportationMod = new Backbone.Model({ 'asset': '/api/v1/asset/'+this.assetID+'/', 'export_configuration': '/api/v1/exportconfiguration/'+this.model.get('id')+'/' });
exportationMod.url = '/api/v1/exportation/';
exportationMod.save();
OK so the server is running with django + tastypie. Should this be validated by the client by first making an extra query, on the server (maybe there is a way of setting a combination of unique keys like mysql), or is there another setting I can tweak so it edits instead of creating?
If you pass data to the server without some unique id, how would the server know what to update?
If it makes sense for your situation, you can override isNew() in your model.
var MyModel = Backbone.Model.extend({
idAttribute: 'somethingUnique',
url: '/api/v1/exportation/',
isNew: function(){
// return true if you want create (POST),
// return false if you want update (PUT)
}
});
By default it looks like this (with the above model, this.id would be the idAttribute value above):
// A model is new if it has never been saved to the server, and lacks an id.
isNew: function() {
return this.id == null;
},
If you want to edit something that already exists on the server, you should just fetch it first before editing/saving it. Also, if there is some unique id that is not called 'id' you can override that on the model as well (see above).
Trying to make a simple application in rails 3.
If I create a team model with rails g scaffold team name:string && rake db:migrate, then run rake, I get success from the prebuilt tests.
If I simply add validates_uniqueness_of :name to the team model. The functional tests fail with
1) Failure:
test_should_create_team(TeamsControllerTest) [/test/functional/teams_controller_test.rb:20]:
"Team.count" didn't change by 1.
<3> expected but was
<2>.
I modified tests/fixtures/teams.yml to look like this:
one:
name: MyString
two:
name: MyString2
The test still fails.
It can't get much more basic than this; what have I missed?
Fixtures basically represent model instances that are in the database.
If you look at the top of test/functional/teams_controller_test.rb you'll see
setup do
#team = teams(:one)
end
and then in your failing functional test you'll have
post :create, :team => #team.attributes
This is what's happening: you're trying to create a new team with the same attributes as "the team fixture named :one". Since both would have the same name (since they have the exact same attributes), the uniqueness validation is failing.
Try replacing your setup block with this
setup do
#team = teams(:one)
#team.name = 'unique name'
end
Now you'll be creating a new team with the name 'unique name' (which isn't in the database according to the fixtures), and your test will pass.