In JUnit 3, I could get the name of the currently running test like this:
public class MyTest extends TestCase {
public void testSomething() {
assertThat(getName(), is("testSomething"));
}
}
How do I do this in spock? I would like to use the test name as a key in a shared resource so that tests don't interfere with each other.
One solution is to leverage JUnit's TestName rule:
import org.junit.Rule
import org.junit.rules.TestName
class MySpec extends Specification {
#Rule TestName name = new TestName()
def "some test"() {
expect: name.methodName == "some test"
}
}
This requires JUnit 4.7 or higher.
For spock 1.0-groovy-2.4 you can try :
def "Simple test"() {
expect:
specificationContext.currentIteration.name == "Simple test"
}
Related
I have a class in src/groovy like this
public class MyClass {
#AutoWired
SomeOtherClass someOtherClass
String test() {
return someOtherClass.testMethod()
}
}
When I write a test for this method I am getting an error: Cannot invoke method testMethod() on null object.
This is my test :-
def "test test" () {
expect:
myClass.test() == "somevalue"
}
What am I doing wrong? Is there a way to mock the #Autowired class?
You need to mock your someOtherClass. Something like this
def "test test"(){
setup:
myClass.someOtherClass = Mock(SomeOtherClass)
myClass.someOtherClass.testMethod() >> "somevalue"
expect:
myClass.test() == "somevalue"
}
Though the previous answer should work, spock provide more elegant way of injecting beans as per need. You could use doWithSpring closure to declare beans just like spring dsl support provided in grails using resources.groovy.
class MyClass extends Specification{
def setup(){
static doWithSpring={
someOtherClass(SomeOtherClass)
//declare below if want to inject myClass somewhere else as a bean else not
/*myClass(MyClass){bean->
someOtherClass = someOtherClass
}*/
}
}
def "test test" () {
expect:
myClass.test() == "somevalue"
}
}
I'd like to be able to log the spock feature names and clause labels when running some automated tests. This would help with debugging test issues when using a headless browser for automation, specifically phantomjs. Reason being, phantomjs does not always behave the same way as when using the chrome WebDriver. It would also be nice to have if this is even possible.
def "Login logout test"(){
given: "Go to login page"
...
when: "Submit username and password"
...
then: "Dashboard page displayed"
...
when: "logout"
...
then: "Returned to login page"
...
}
For example, It would be cool if I could get the above sample spock feature method to log the labels like this.
Login logout test
Go to login page
Submit username and password
logout
Returned to login page
Step1: Create a Your own spock extension Class
package com.example.spock.exetension;
public class MySpockExtension implements IGlobalExtension {
#Override
public void start() {
}
#Override
public void visitSpec(SpecInfo spec) {
spec.addListener(new MyCustomSpockRunListener());
}
#Override
public void stop() {
}
}
Step2: Create a RunListener that can listen to a spock run
package com.example.spock.exetension;
public class MyCustomSpockRunListener extends AbstractRunListener {
private boolean specFailed;
private boolean featureFailed;
#Override
public void beforeSpec(SpecInfo spec) {
// TODO Auto-generated method stub
specFailed = false;
}
#Override
public void beforeFeature(FeatureInfo feature) {
// TODO Auto-generated method stub
featureFailed = false;
}
#Override
public void beforeIteration(IterationInfo iteration) {
}
#Override
public void afterIteration(IterationInfo iteration) {
}
#Override
public void afterFeature(FeatureInfo feature) {
// TODO Auto-generated method stub
for ( BlockInfo block : feature.getBlocks() ) {
System.out.println(block.getKind().name() + " : " + block.getTexts() );
}
}
#Override
public void afterSpec(SpecInfo spec) {
// TODO Auto-generated method stub
System.out.println(spec.getName() + " : STATUS : " + specFailed != null ? "failure":"success");
}
#Override
public void error(ErrorInfo error) {
specFailed = true;
FeatureInfo feature = error.getMethod().getFeature();
if (feature != null) {
featureFailed = true;
System.out.println(error.getMethod().getName() + " : " + error.getException());
}else {
}
}
#Override
public void specSkipped(SpecInfo spec) {
}
#Override
public void featureSkipped(FeatureInfo feature) {
}
}
Step3: Register your new Spock extension
In your classpath or resource path create a below folder structure META-INF/services/org.spockframework.runtime.extension.IGlobalExtension
Have this as the content of file com.example.spock.exetension.MySpockExtension
Step4: Run your spock test and you should see output something like this.
given: "Go to login page"
when: "Submit username and password"
then: "Dashboard page displayed"
when: "logout"
then: "Returned to login page"
Login logout test : STATUS : success
You can get the name of every feature method by following :
import spock.lang.Specification
import org.junit.Rule
import org.junit.rules.TestName
import org.slf4j.Logger
import org.slf4j.LoggerFactory
class MySpec extends Specification{
private static Logger logger = LoggerFactory.getLogger(ClassName.class)
#Rule TestName testName = new TestName()
void setup(){
def featureMethodName = testName.methodName
logger.info("feature method : " + featureMethodName)
}
}
PiggyBacking on #Raghu Kirans answer, I had to do a little bit more to get this to run the way that I wanted with Data Driven tests. In the BeforeIteration method of your RunListener I did the following:
#Override
public void beforeIteration(IterationInfo iteration) {
Optional.of(iteration)
.map(feature -> iteration.getFeature())
.map(FeatureInfo::getBlocks)
.ifPresent( blocks -> blocks.forEach(
blockInfo -> log.info(blockInfo.getKind().name() + " : " + blockInfo.getTexts())));
}
This simply prints out everything prior to each iteration. Also note that getKind().name() on the BlockInfo object does not print out the given, when, then of the spock block in our test but instead prints out SETUP, WHEN, THEN and WHERE instead. getTexts() will print out the combined texts of the block.
Example:
given: "I wake up"
and: "I drink a cup of coffee"
Will be displayed as
SETUP : ["I wake up", "I drink a cup of coffee"]
After continuously searching I found this solution for getting the test name. But can't seem to find anything on the 'when' and 'then' labels. This is okay for now.
import org.junit.Rule
import org.junit.rules.TestName
class MySpec extends Specification {
#Rule TestName name = new TestName()
def "some test"() {
expect: name.methodName == "some test"
}
}
You might want to have a look at the Spock Reports Extension
How does one inject properties from the applicaiton.yml file into an integration test in grails 3.0 ?
For ex: I have this property in my applicaiton.yml
----
testing:
defaults:
startUrl: 'http://localhost:8080/'
----
In my Integration Spock test, I have the following code:
class WebpageRolesTestSpec extends Specification {
def grailsApplication
String LOGIN_URL = grailsApplication.config.getProperty('testing.defaults.startUrl')
void "test login screen prompt"() {
expect:
LOGIN_URL == 'http://localhost:8080/'
}
}
The exception i am getting is: Cannot get property 'config' on null object
You could use holders:
import grails.util.Holders
...
LOGIN_URL = Holders.config.testing.defaults.startUrl
...
Below test works for me in Grails 3.1.1, I suppose you would need a clean app.
import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*
#Integration
#Rollback
class SampleSpec extends Specification {
def grailsApplication
void "test something"() {
expect:"fix me"
grailsApplication.config.getProperty('testing.defaults.startUrl') ==
'http://localhost:8080/'
}
}
I am using a service in controller. I am writing unit test for the controller but I am unable to instantiate service in controller. It is always null.
if I instantiate service using new operator in Controller testing class. The services in the service class are not instantiated.
How can I instantiate a service in testing class?
You can let Spring do it for you.
A controller that depends on a service:
// grails-app/controllers/demo/DemoController.groovy
package demo
class DemoController {
def helperService
def index() {
def answer = helperService.theAnswer
render "The answer is ${answer}"
}
}
The service:
// grails-app/services/demo/HelperService.groovy
package demo
class HelperService {
def getTheAnswer() {
42
}
}
A unit test which injects the service:
// src/test/groovy/demo/DemoControllerSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(DemoController)
class DemoControllerSpec extends Specification {
static doWithSpring = {
helperService HelperService
}
void "test service injection"() {
when:
controller.index()
then:
response.text == 'The answer is 42'
}
}
A unit test which injects a fake version of the service:
// src/test/groovy/demo/AnotherDemoControllerSpec.groovy
package demo
import grails.test.mixin.TestFor
import spock.lang.Specification
#TestFor(DemoController)
class AnotherDemoControllerSpec extends Specification {
static doWithSpring = {
helperService DummyHelper
}
void "test service injection"() {
when:
controller.index()
then:
response.text == 'The answer is 2112'
}
}
class DummyHelper {
def getTheAnswer() {
2112
}
}
I am using Grails 2.2.4 and create JUnit Test for controller but code coverage not cover my test case of controller below are my test case detail.
//BuildConfig.groovy
plugins {
test ":code-coverage:2.0.3-3"
}
//MyControllerTests.groovy
#TestMixin(GrailsUnitTestMixin)
#TestFor(MyController)
#TestFor([Domain1,Domain2])
class MyControllerTests {
void setUp() {
controller.myService = new MyService()
}
void testAction1(){
controller.action1()
}
}
//mycontroller.groovy
class MyController {
def myService
def action1{
def msg = myService.myFirstAction()
}
}
//myservice.groovy
class MyService{
def myFirstAction(){
//logic which returns string
return 'my logic result'
}
}