I'm writing a unit test with Spock. I want to check all elements of an array using the spock
when: then:
block. I found the syntax here from the accepted answer. and based on that I wrote something like this -
then:
myArray.every { (it >= 0) && (it < 10) }
This works correctly with IntelliJ but when I build the test using Ant, it fails.
Ant and groovy setup - taken from here. I could see it working for simple conditions like myArray.length == 8.
Groovy version - 2.4.5
Spock version - spock-core-1.0-groovy-2.4.jar
JDK 1.8
Ant 1.9.6
Error -
[junit] Testcase: initializationError took 0 sec
[junit] Caused an ERROR
[junit] Test class should have exactly one public zero-argument constructor
[junit] java.lang.Exception: Test class should have exactly one public zero-argument constructor
[junit] at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
[junit]
[junit] Testcase: initializationError took 0 sec
[junit] Caused an ERROR
[junit] No runnable methods
[junit] java.lang.Exception: No runnable methods
[junit] at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
[junit]
[junit] Test package.MyTest$__spock_feature_0_0_closure1 FAILED
On looking at the class file created by the ant build, I see
public void $spock_feature_0_0(Object obj){
...
...
class __spock_feature_0_0_closure1 extends Closure implements GeneratedClosure {
}
...
...
new __spock_feature_0_0_closure1()
}
So looks like the closure is not accessible using Reflection!! Any thoughts?
Is my ant groovy configuration messed up(as I said earlier, simpler tests are working for me, so i hope not!)?, or am i just expecting too much from Spock.
An example of the scenario -
public class SpockTest extends Specification{
public def "example"(){
given:
int[] arr = new int[5];
when:
arr[0] = 1;
then:
arr.every { (it >= 0) }
}
}
Below junit also fails to run with the same error-
public class TestClass {
public int test1() {
class testInner {//local class
int a = 100;
public int getA() {
return a;
}
}
return new testInner().getA();
}
#Test
public void test2() {
System.out.println(test1());
assert 100 == test1();
}
}
UPDATE(29-Feb-16) - With the discussions so far, it seems like the problem is with Ant. Only the junit and groovy/Spock tests using/compiling to local classes are giving errors. Simpler cases are working fine.
Related
I am trying to make use of {throw new Exception()} in Spock, but on running the test it prints in report--
"The following problems occurred:
Expected exception of type 'java.lang.Exception', but no exception was thrown"
package testing
import spock.lang.Specification
class MyFirstSpec extends Specification {
def "Test_One" (){
given:
def obj = new SpockMethodsPlaceholder()
obj.returnAge(0) >> {throw new Exception("invalidAge")}
when:
1*obj.returnAge(0)
then:
Exception ex = thrown()
ex.getMessage() == "invalidAge"
}
class SpockMethodsPlaceholder {
def "returnAge" (int age){
return age
}
}
}
Is there something wrong with my code?
Below is the stack trace of test run---
Working Directory:
Gradle User Home: /home/mafia/.gradle
Gradle Distribution: Gradle wrapper from target build
Gradle Version: 4.3
Java Home: /usr/lib/jvm/java-8-oracle
JVM Arguments: None
Program Arguments: None
Build Scans Enabled: false
Offline Mode Enabled: false
Tests: testing.MyFirstSpec
:compileJava UP-TO-DATE
:compileGroovy NO-SOURCE
:processResources NO-SOURCE
:classes UP-TO-DATE
:compileTestJava
:compileTestGroovy
:processTestResources NO-SOURCE
:testClasses
:test
testing.MyFirstSpec > Test_One FAILED
org.spockframework.runtime.WrongExceptionThrownError at MyFirstSpec.groovy:16
1 test completed, 1 failed
There were failing tests. See the report at: file:///media/mafia/A08200E98200C62E/Study/Git_Repo/GIT_JAVA/workbench/SpockProject/build/reports/tests/test/index.html
BUILD SUCCESSFUL in 19s
4 actionable tasks: 3 executed, 1 up-to-date
It looks like you misunderstand the concept of stubbing/mocking
What exactly is tested? Class SpockMethodPlaceholder? In this case it should not be mocked/ stubbed its a "class-under-test" - the code that you check and want to gain a confidence that it works (the code in the methods of this class if you wish)
On the other hand, if you use >> syntax you probably do intend to Stub something.
So here is a better example:
public class SomeClass {
public int return getAge(int age) {
if(age <= 0) {
throw new IllegalArgumentException("too young");
} else {
return age;
}
}
}
class SomeClassTest extends Specification {
def "an exception is thrown if the person is too young" () {
given:
def subject = new SomeClass()
when:
subject.getAge(-1)
then:
def ex = thrown(IllegalArgumentException)
ex.message == "too young"
}
}
BaseTest.java:
private static ReportService reportService; // Calling report service interface
#BeforeSuite:
reportService = new ExtentReportService(getConfig()); // New instance of ExtentReportService.
#BeforeMethod:
reportService.startTest(testname); // Starting the test and passing the name and description of the test.
#AfterMethod:
reportService.endTest(); // Ending the test
#AfterSuite:
reportService.close(); // Closing the test
**ExtentReportService.java:** // Contains different extent API methods. (These are designed to be generic.)
protected static ExtentReports extent; // static instance of ExtentReports
protected static ExtentTest test; //static instance of ExtentTTest
#Override // StartTest method
startTest(Method method) {
testMetaData = getTestMetaData(method);
test=extent.startTest(testMetaData.getId(),testMetaData.getSummary());
}
#Override //End test method
endTest() {
extent.endTest(test);
extent.flush();
}
The above is my selenium code.
When I am executing my suite file with parallel="methods" and thread count="3", I am getting the following error: "com.relevantcodes.extentreports.ExtentTestInterruptedException: Close was called before test could end safely using EndTest.".
While debugging, I found that even before all endTest() in AfterMehtod were executed, AfterSuite was being called.
I tried different variations such that the code works, such as, removing static, calling endTest() in the test itself rather than after method, removing close() call from AfterSuite and many other variations. But still getting the same error.
I tried all the possible solutions given on the internet, but to no use.
Attaching a hierarchy file for the ExtentReport used in my project
I also the following solution given in StackOverflow:
Extent report :com.relevantcodes.extentreports.ExtentTestInterruptedException: Close was called before test could end safely using EndTest
Unsynchronized output
XMF file for parallel test.
ExtentReports Intialized in ExtentManager class using Singleton().
public class ExtentManager {
private static ExtentReports extent;
public static ExtentReports getInstance() {
if(extent == null) {
extent = new ExtentReports(System.getProperty("user.dir")+"\target\surefire-reports\html\extent.html", true, DisplayOrder.OLDEST_FIRST);
extent.loadConfig(new File(System.getProperty("user.dir")+"src\test\resources\extentconfig\ReportsConfig.xml"));
}
return extent;
}
}
Declared in TestBase class as global.
public ExtentReports repo= ExtentManager.getInstance();
public static ExtentTest test
Call startTest in public void onTestStart(ITestResult result)
test = repo.startTest(result.getName().toUpperCase());
Call endTest in CustomListener Class both in a)public void onTestFailure(ITestResult result); b)public void onTestSuccess(ITestResult result).
repo.endTest(test)
Call close() OR flush() in #AfterSuite in TestBase class but NOT both!
//repo.close();
repo.flush();
Note: I have ExtentReports ver-2.41.2, and TestNg ver-7.1.0.
After the above steps, error 'Getting closed before endTest call in Selenium using Extent Reports' got resolved.
Extent report generates each test successfully in the report.
Try it out!
I'm testing a Grails application but i get this error message:
I'm trying to do unit test. My Grails version is 2.4.3
Error executing script TestApp: java.lang.ClassNotFoundException: grails.plugin.spock.
That's my code:
#TestFor(TrackEmailController)
#Mock(TrackEmail)
class TrackEmailUnit2Spec extends Specification {
def setup() {
}
def cleanup() {
}
void "test something"() {
}
void 'test mandrillEventsEndPoint'() {
when:
controller.mandrillEventsEndPoint()
then:
response.text == 'mandrill Events End Point'
}
}
Can you be a little more specific on how you are running your test cases and how you have integrated spock dependencies? Or perhaps provide a github link to replicate the issue?
With grails 2.5.1, I only created a service with a simple property initialized through a constructor (#PostConstruct also)
Any unit test that read this property through a service method get a NullPointerException
Here's how to reproduce:
grails> create-app acme
grails> create-service DataService
acme/DataService.groovy
#Transactional
class DataService {
def data = null;
#PostConstruct
def setup() {
if (data == null) {
println("Initializing the service ...")
data = "<DATA>"
}
}
def serviceMethod() {
setup()
}
def getDataLength() {
println("Getting data length ...")
return data.length(); // Line 26
}
}
acme/DataServiceSpec.groovy
#TestFor(DataService)
class DataServiceSpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test data"() {
given:
int datalen = service.getDataLength()
expect:
datalen > 0
}
}
Running the test ....
grails> test-app -unit -echoOut
The output ...
|Running 2 unit tests...
|Running 2 unit tests... 1 of 2
--Output from test data--
Initializing the service ...
Getting data length ...
Failure: |
test data(acme.DataServiceSpec)
|
java.lang.NullPointerException: Cannot invoke method length() on null object
at acme.DataService.getDataLength(DataService.groovy:26)
at acme.DataServiceSpec.test data(DataServiceSpec.groovy:20)
|Completed 1 unit test, 1 failed in 0m 2s
.Tests FAILED
The log shows the property initialization step and the NullPointerException for the property.
The questions are:
Why the 'data' property becomes null ?
There's a service lifecycle setting the property to null ?
Is the running test using a different DataService instance from the initialized instance ?
Have you seen Grails unit test fails on #PostConstruct?
In unit test and with #TestFor annotation #PostConstruct is not called. You can create construct for test or call setup method.
import grails.test.mixin.integration.Integration
import spock.lang.Specification
#Integration
class MySpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test something"() {
expect:"tests a"
true
}
}
MySpec > test something FAILED
java.lang.IllegalStateException
Caused by: org.springframework.beans.factory.BeanCreationException
Caused by: org.springframework.beans.factory.BeanCreationException
Caused by: org.springframework.beans.factory.BeanCreationException
Caused by: java.lang.NullPointerException
1 test completed, 1 failed
:integrationTest FAILED
:mergeTestReports
I run
"test-app -integration MySpec" command
Is that an error in grails or I do smth wrong?
UPDATE!
I found a solution - just add
testCompile "org.grails.plugins:hibernate"
to build.gradle
Testing was never so easy and intuitive before the use of Spock.We can always test the exceptions in grails Spock Testing. For example we have a method which throws exception like :
String getUserType(int age){
if(age<=0){
throw new MyException("Invalid age")
}else if( age>0 && age<50){
return "Young"
}else{
return "Old"
}
}
Now we will write the test case of this method for checking whether exception is thrown for invalid inputs or not.
def "exception should be thrown only for age less than or equal to 0"{
given:
String type = getUserType(34)
expect:
type == "Young"
notThrown MyException
when:
type = getUserType(0)
then:
thrown MyException
}
This is how we have tested whether exception is thrown for invalid input or not.
Hope it helps