I use Spock to test an action of a controller as below:
code in controller:
def milestoneChange() {
Milestones selectedMilestone = dataQueryService.getMilestone(params.id)
Tasks[] tasksList = dataQueryService.getTasksList(params.id)
List enumerateNameList = dataQueryService.getEnumerateNameList()
render(template: 'milestoneSummary', model: [selectedMilestone: selectedMilestone, tasksList: tasksList, enumerateNameList: enumerateNameList, selectedMilestoneID: params.id])
}
code in test:
#TestFor(MilestonesMgtController)
class MilestonesMgtControllerSpec extends Specification {
void "change the milestone"() {
when:
views['/milestonesMgt/_milestoneSummary.gsp'] = "test"
controller.params.id = 'Late Stage Review'
controller.milestoneChange()
then:
controller.response.text == 'test'
}
}
Because the content of the _milestoneSummary.gsp is very long, I use the approach mentioned in both Grails documentation and http://www.javacodegeeks.com/2013/09/grails-goodness-unit-testing-render-templates-from-controller.html which is using views['/milestonesMgt/_milestoneSummary.gsp'] to mock the template. However, the response is still the original long content? Does anyone know what is wrong with my code? Thanks very much!!!
BTW when using params/response/model, I have to use controller.xxx, but I see the sample code in documentation use params/response/model directly, do you know why?
I am using Grails 2.3.8
the project link http://github.com/jackyying1130/MMS
the test is located in MMS/test/integration/phdmilestonemanagementsystem/MilestonesMgtControllerSpec.groovy
Related
I have grails 2.4.4 and Cobertura as covert test.
I have code like:
lstPerspectives = Perspectives.findAllByDbAndSysDelete(dbInstance, new Long(0))
But Cobertura don´t pass the test because don´t search in my DB, How can I pass this line?, How can overwrite this value? I send this lstPerspectives but it don´t take it.
Thanks
Thanks
Try something like the following:
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
#TestFor(Perspectives)
#Mock([Perspectives])
class PerspectivesSpec
{
void "test Perspectives"(){
given:
def dbInstance = 'aDbInstance' // don't know what this is
def sysDelete = false // is this a boolean?
new Perspectives( dbInstance: dbInstance, sysDelete: sysDelete ).save( failOnError: true )
when:
// run you bit of code that executes the snippet in your question
then:
// check your desired outcome
}
}
I don't know if you are testing your Perspectives class directly here or something else, controller, service? so had to make a few assumptions.
I have a grails 3.1.x project with lots of controllers and I use spock for testing the controllers.
I use a command pattern for my controllers so each action takes a command object.
An example for such a controller :
class PlaygroundController {
public Object pg(PgCO pgco) {
String s = null
if (pgco.one) {
s = pgco.one
}
if (pgco.two) {
s = pgco.two
}
render view: 'pg', model: [resultat: s]
}
}
I have a simple spock test case:
void "pg"() {
given:
PgCO pgCO = new PgCO()
pgCO.one = 'TEST'
when:
controller.pg(pgCO)
then:
view == '/playground/pg'
model
model.resultat == 'TEST'
}
This test runs fine, but when i run a jacocoTestReport it shows that my coverage is way below 50% , it's fine that it's not fully covered since I'm only covering one branch.
But the report contains loads of "missed instructions" on methods that I have no source code for.. specially there is a shadow pg() method that doesn't take any parameters. Grails injects this method, but I will never call that method from my tests since I use the command object version of the same method. this method but also a lot of other methods coming from grails controller framework.
Isn't there anyw ay to tell jacoco that it's only the "source code" that needs to be checked for coverage ?
I've tried specifying exact source dirs, but this doesn't help
Here's an image of the coverage report:
coverage report
I have a daily simple project just enabling the jacoco plugin, and running latest jacoco :
jacoco {
toolVersion = "0.7.5.201505241946"
}
Have anyone else a solution to this ?
So, I have this pretty simple Spec below. I have a class that is not a controller or service or anything like that. It's a Job class. It depends on two services: updateService and directoryTypeService. It runs a Redis async job and it's under /grails-app/jobs folder.
All I want is to make sure that whenever I invoke this job#perform() method (which return type is void), a given dependent method called UpdateService#completeClaiming is invoked, but UpdateService#requestNewPin is not. (Listing is a domain class, by the way).
When I run this Spec, I keep getting an error message saying: "No more calls to 'completeClaiming' expected at this point. End of demands."
What am I doing wrong here? Any wild guesses?
#Mock(Listing)
class SubmissionJobSpec extends Specification {
def directoryTypeServiceMock
def updateServiceMock
def job
def setup(){
job = new SubmissionJob()
directoryTypeServiceMock = mockFor(DirectoryTypeService)
updateServiceMock = mockFor(UpdateService)
job.updateService = updateServiceMock.createMock()
job.directoryTypeService = directoryTypeServiceMock.createMock()
}
def "if the directory is enabled and the pin status is ENTERED, we should call updateService.completeClaiming"() {
given:
directoryTypeServiceMock.demand.isUpdateEnabled { DirectoryType d, Country c -> return true}
new Listing(
location: new Location(country: Country.DE)
).save(failOnError: true, validate: false)
when:
job.perform(Listing.last().id, true)
then:
1 * updateServiceMock.completeClaiming(Listing.last(), true) >> new ListingEvent(output: [success: true])
0 * updateServiceMock.requestNewPin(_ as Listing, true)
}
You seem to be confusing Groovy and Spock mocks. You can't use Spock mocking syntax (e.g. 0 * updateServiceMock.requestNewPin(_ as Listing, true)) for a Groovy mock created with mockFor(). Spock mocks are created using Mock(), Stub() or Spy(). I'm not aware of any good reason to use a Groovy mock in a Spock spec.
I'm entirely new to Grails and it's testing functions since I started my current job approx 4 months ago. The person who trained me on testing left our group several weeks ago, and now I'm on my own for testing. What I've slowing been discovering is that the way I was trained on how to do Grails integration testing is almost entirely different from the way(s) that I've seen people do it on the forums and support groups. I could really use some guidance on which way is right/best. I'm currently working in Grails 2.4.0, btw.
Here is a sample mockup of an integration test in the style that I was trained on. Is this the right or even the best way that I should be doing it?
#Test
void "test a method in a controller"() {
def fc = new FooController() // 1. Create controller
fc.springSecurityService = [principal: [username: 'somebody']] // 2. Setup Inputs
fc.params.id = '1122'
fc.create() // 3. Call the method being tested
assertEquals "User Not Found", fc.flash.errorMessage // 4. Make assertions on what was supposed to happen
assertEquals "/", fc.response.redirectUrl
}
Since Grails 2.4.0 is used, you can leverage the benefit of using spock framework by default.
Here is sample unit test case which you can model after to write Integration specs.
Note:
Integration specs goes to test/integration
should inherit IntegrationSpec.
Mocking is not needed. #TestFor is not used as compared to unit spec.
DI can be used to full extent. def myService at class level will inject the service in
spec.
Mocking not required for domain entities.
Above spec should look like:
import grails.test.spock.IntegrationSpec
class FooControllerSpec extends IntegrationSpec {
void "test a method in a controller"() {
given: 'Foo Controller'
def fc = new FooController()
and: 'with authorized user'
fc.springSecurityService = [principal: [username: 'somebody']]
and: 'with request parameter set'
fc.params.id = '1122'
when: 'create is called'
fc.create()
then: 'check redirect url and error message'
fc.flash.errorMessage == "User Not Found"
fc.response.redirectUrl == "/"
}
}
It's probably going to be one of the lame and novice level questions but I'm struggling with it for some time and it's still not working.
I have a HomeController:
package example
class HomeController {
def index = {
[ message: "Hello, world!" ]
}
}
Now I've installed easyb plugin:
grails install-plugin easyb
I've also created a basic story for this controller (in "test/unit" folder):
scenario "Should return 'Hello, world!' message", {
given "Controller is instantiated", {
mockController HomeController
controller = new HomeController()
}
when "Controller received request for index action"
and "No additional parameters are expected", {
result = controller.index()
}
then "Controller displays Hello, world!", {
result.message.shouldBe "Hello, world!"
}
}
When I run the easyb tests
grails test-app unit:easyb
instead of this test passing as it should I get the following error message at "when No additional parameters are expected":
[FAILURE: No signature of method: HomeController.index() is applicable for argument types: () values: []]
and then for the second part at "then Controller displays Hello, world!"
[FAILURE: No such property: result for class: HomeController]
I'm basically following the instructions from http://grails.org/plugin/easyb.
Can anyone explain to me what I'm doing wrong?
Matthias.
Oh well, I found it... conventions, conventions, conventions....
Naming the scenario file HomeController.story forced the engine to include "controller" variable in the scope. What's not clear though is why I couldn't do it again...
Nevermind. After removing the "given" part completely it works as it should.