4developers 2015: testowanie ze spockiem - dominik przybysz
TRANSCRIPT
![Page 1: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/1.jpg)
SpockDominik Przybysz
https://github.com/alien11689/spock-show
[email protected] @alien11689 http://przybyszd.blogspot.com
![Page 2: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/2.jpg)
Context
![Page 3: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/3.jpg)
Person.groovy@Canonicalclass Person { String firstName String lastName Integer age
boolean isAdult() { age >= 18 }}
![Page 4: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/4.jpg)
PersonValidator.java Part. 1@Componentpublic class PersonValidator { public void validatePerson(Person person) { String firstName = person.getFirstName(); if (firstName == null || firstName.length() == 0) { throw new PersonValidationException("First name must be given"); } String lastName = person.getLastName(); if (lastName == null || lastName.length() == 0) { throw new PersonValidationException("Last name must be given"); }
![Page 5: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/5.jpg)
PersonValidator.java Part. 2 Integer age = person.getAge(); if (age == null){ throw new PersonValidationException("Age must be given"); } if( age < 0) { throw new PersonValidationException("Age cannot be negative"); } }}
![Page 6: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/6.jpg)
PersonValidationException.java
public class PersonValidationException extends RuntimeException { public PersonValidationException(String message) { super(message); }}
![Page 7: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/7.jpg)
PersonDao.groovy Part. 1
@Componentclass PersonDao { final JdbcTemplate jdbcTemplate
@Autowired PersonDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate }
![Page 8: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/8.jpg)
PersonDao.groovy Part. 2void persist(List<Person> persons) { persons.each { persist(it) } }
@Transactional void persist(Person person) { jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('${person.firstName}', '${person.lastName}', ${person.age})") }
![Page 9: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/9.jpg)
PersonDao.groovy Part. 3 List<Person> findByLastName(String lastName) { jdbcTemplate.queryForList("select first_name, last_name, age from person where last_name = ?", [lastName] as Object[]) .collect({Map row -> new Person(row.first_name, row.last_name, row.age) }) }
void close() { println "Closing person dao" }}
![Page 10: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/10.jpg)
PersonController.groovy Part. 1@Componentclass PersonController { final PersonValidator personValidator final PersonDao personDao
@Autowired PersonController(PersonValidator personValidator, PersonDao personDao) { this.personValidator = personValidator this.personDao = personDao }
![Page 11: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/11.jpg)
PersonController.groovy Part. 2
void addPerson(Person person) { personValidator.validatePerson(person) personDao.persist(person) }}
![Page 12: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/12.jpg)
PersonContextConfiguration.groovy Part. 1
@Configuration@ComponentScan("com.blogspot.przybyszd.spock")class PersonContextConfiguration { @Bean JdbcTemplate getJdbcTemplate(DataSource dataSource){ return new JdbcTemplate(dataSource) }
![Page 13: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/13.jpg)
PersonContextConfiguration.groovy Part. 2 @Bean DataSource getDataSource() { BasicDataSource basicDataSource = new
BasicDataSource() basicDataSource .setDriverClassName("org.h2.Driver") basicDataSource.setUrl("jdbc:h2:mem:personDB;DB_CLOSE_DELAY=1000;INIT=runscript from 'classpath:db/person.sql';") basicDataSource.setUsername("sa") basicDataSource.setPassword("") return basicDataSource }}
![Page 14: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/14.jpg)
Introduction
![Page 15: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/15.jpg)
Dependenciescompile 'org.codehaus.groovy:groovy-all:2.4.0'compile 'org.springframework:spring-jdbc:4.0.5.RELEASE'compile 'org.springframework:spring-beans:4.0.5.RELEASE'compile 'org.springframework:spring-context:4.0.5.RELEASE'compile 'commons-dbcp:commons-dbcp:1.4'compile 'com.h2database:h2:1.4.178'
testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4'testCompile 'org.springframework:spring-test:4.0.5.RELEASE'testCompile 'cglib:cglib-nodep:3.1'testCompile 'org.objenesis:objenesis:2.1'
![Page 16: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/16.jpg)
when-then blocks
class PersonTest extends Specification { def "should set first name from constructor"() { when: Person person = new Person(firstName: "Bob") then: person.firstName == "Bob" }}
![Page 17: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/17.jpg)
Test failed output
person.firstName == "Bob"| | || Bb false| 1 difference (66% similarity)| B(-)b| B(o)bcom.blogspot.przybyszd.spock.dto.Person(Bb, null, null)
![Page 18: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/18.jpg)
Block with description
def "should set first name from constructor 2"() { when: "person with set first name" Person person = new Person(firstName: "Bob") then: "person has first name" person.firstName == "Bob"}
![Page 19: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/19.jpg)
Given block
def "should set first name from setter"() { given: Person person = new Person(firstName: "Bob") when: person.firstName = 'Tom' then: person.firstName == "Tom"}
![Page 20: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/20.jpg)
Multiple asserts
def "should set person data from constructor"() { when: Person person = new Person("Bob", "Smith", 15) then: person.firstName == "Bob" person.lastName == "Smith" person.age == 15}
![Page 21: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/21.jpg)
Multiple when then
def "should set first name from constructor and change with setter"() { when: Person person = new Person(firstName: "Bob") then: person.firstName == "Bob" when: person.firstName = "Tom" then: person.firstName == "Tom"}
![Page 22: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/22.jpg)
And block
def "should set first name and last name"() { when: Person person = new Person(firstName: "Bob", lastName: "Smith") then: person.firstName == "Bob" and: person.lastName == "Smith"}
![Page 23: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/23.jpg)
Expect block
def "should compare person with equals"() { expect: new Person("Bob", "Smith", 15) == new Person("Bob", "Smith", 15)}
![Page 24: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/24.jpg)
Lifecycle
![Page 25: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/25.jpg)
Test fields
class LifecycleSpockTest extends Specification {
@Shared StringWriter writer
Person person
}
![Page 26: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/26.jpg)
Setup specification
def setupSpec() { println "In setup spec" writer = new StringWriter()}
![Page 27: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/27.jpg)
Setup each test
def setup() { println "In setup" person = new Person(firstName: "Tom", lastName: "Smith", age: 21)}
![Page 28: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/28.jpg)
Cleanup each test
def cleanup() { println "In cleanup" person = null}
![Page 29: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/29.jpg)
Cleanup specification
def cleanupSpec() { println "In cleanup spec" writer.close()}
![Page 30: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/30.jpg)
Setup and clenup blocks
def "should check firstName"() { setup: println "setup in test" println "should check firstName" expect: person.firstName == "Tom" cleanup: println "Cleanup after test"}
![Page 31: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/31.jpg)
Statements without block
def "should check lastName"() { println "should check lastName" expect: person.lastName == "Smith"}
![Page 32: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/32.jpg)
Parameters
![Page 33: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/33.jpg)
Parameters in table@Unrolldef "should set person data"() { when: Person person = new Person(lastName: lastName, firstName: firstName, age: age) then: person.firstName == firstName person.lastName == lastName person.age == age where: lastName | firstName | age "Smith" | "John" | 25 "Kowalski" | "Jan" | 24}
![Page 34: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/34.jpg)
Parameters in method signature@Unrolldef "should set person data 2"(String firstName, String lastName, int age) { // … where: lastName | firstName | age "Smith" | "John" | 25 "Kowalski" | "Jan" | 24}
![Page 35: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/35.jpg)
Parameters in method name@Unrolldef "should set person with #lastName, #firstName and #age"() { // … where: lastName | firstName | age "Smith" | "John" | 25 "Kowalski" | "Jan" | 24}
![Page 36: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/36.jpg)
Call parameterless method in test name Part 1
@Unroll("should set person with #lastName.length(), #firstName.toUpperCase() and #age")
![Page 37: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/37.jpg)
Call parameterless method in test name Part 2
@Unroll("should set person with #lastName.length(), #firstName.toUpperCase() and #age when last name starts with #firstLetter")def "should set person with lastName, firstName and age 3"() { //… where: lastName | firstName | age "Smith" | "John" | 25 "Kowalski" | "Jan" | 24
firstLetter = lastName.charAt(0)}
![Page 38: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/38.jpg)
Separeted table
@Unrolldef "should check if person is adult with table"() { expect: new Person(age: age).isAdult() == adult where: age || adult 17 || false 18 || true 19 || true}
![Page 39: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/39.jpg)
Parameters from list
@Unrolldef "should check if person is adult with list"() { expect: new Person(age: age).isAdult() == adult ageSquare == age * age where: age << [17, 18, 19] adult << [false, true, true] ageSquare = age * age}
![Page 40: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/40.jpg)
Parameters from list of list
@Unrolldef "should check if person is adult with list 2"() { expect: new Person(age: age).isAdult() == adult where: [age, adult] << [[17,false], [18,true], [19, true]]}
![Page 41: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/41.jpg)
One paramter table
@Unrolldef "should set first name"() { when: Person person = new Person(firstName: firstName) then: person.firstName == firstName where: firstName | _ "John" | _ "Jan" | _}
![Page 42: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/42.jpg)
Parameters from db - setupstatic Sql sql = Sql.newInstance("jdbc:h2:mem:", "sa", "", "org.h2.Driver")
def setupSpec() { sql.execute("""DROP TABLE IF EXISTS person; CREATE TABLE person ( first_name VARCHAR(256) NOT NULL, last_name VARCHAR(256) NOT NULL, age INT NOT NULL );""") sql.executeInsert("""INSERT INTO person (first_name, last_name, age) VALUES ('Tom', 'Smith', 24), ('Jan', 'Kowalski', 30);""")}
![Page 43: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/43.jpg)
Parameters from db - cleanup
def cleanupSpec() { sql.close()}
![Page 44: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/44.jpg)
All parameters from db@Unrolldef "should set person data with #lastName, #firstName and #age"() { // … where: [firstName, lastName, age] << sql.rows("SELECT * FROM person;")}
![Page 45: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/45.jpg)
All parameters from db by name@Unrolldef "should set person data with #lastName, #firstName and #age"() { // … where: [firstName, lastName, age] << sql.rows("SELECT first_name, last_name, age FROM person;")}
![Page 46: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/46.jpg)
Drop last parameter@Unrolldef "should set person data with #lastName, #firstName and #age"() { // … where: [firstName, lastName] << sql.rows("SELECT * FROM person;")}
![Page 47: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/47.jpg)
Omit parameter@Unrolldef "should set person data with #lastName, #firstName and #age"() { // … where: [_, lastName, age] << sql.rows("SELECT * FROM person;")}
![Page 48: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/48.jpg)
Exceptions
![Page 49: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/49.jpg)
Not thrown exceptionPersonValidator sut = new PersonValidator()
def "should pass validation"() { given: Person person = new Person(firstName: "Tom", lastName: "Smith", age: 30) when: sut.validatePerson(person) then: notThrown(PersonValidationException)}
![Page 50: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/50.jpg)
Not thrown exception - fails
Expected no exception of type 'com.blogspot.przybyszd.spock.bean.PersonValidationException' to be thrown, but got it nevertheless
![Page 51: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/51.jpg)
Thrown exception@Unrolldef "should not pass validation"() { then: PersonValidationException exception = thrown(PersonValidationException) exception.message == message where: firstName | lastName | age | message "Tom" | "Smith" | -1 | "Age cannot be negative" "" | "Kowalski" | 19 | "First name must be given" "Jan" | null | 19 | "Last name must be given"}
![Page 52: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/52.jpg)
Thrown exception - another exception
Expected exception of type 'com.blogspot.przybyszd.spock.bean.PersonValidationException', but got 'java.lang.RuntimeException'
![Page 53: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/53.jpg)
Thrown exception - but no exception
Expected exception of type 'com.blogspot.przybyszd.spock.bean.PersonValidationException', but no exception was thrown
![Page 54: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/54.jpg)
Mocking and stubbing
![Page 55: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/55.jpg)
Creating mock
JdbcTemplate jdbcTemplate = Mock(JdbcTemplate)
PersonDao sut = new PersonDao(jdbcTemplate)
![Page 56: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/56.jpg)
Validate mock calls
def "should persist one person"() { given: Person person = new Person("John", "Smith", 20) when: sut.persist(person) then: 1 * jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('John', 'Smith', 20)")}
![Page 57: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/57.jpg)
Mock not called
Too few invocations for:
1 * jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('John', 'Smith', 20)") (0 invocations)
Unmatched invocations (ordered by similarity):
None
![Page 58: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/58.jpg)
Too many calls
1 * jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('John', 'Smith', 20)") (2 invocations)
Matching invocations (ordered by last occurrence):
2 * jdbcTemplate.execute('Insert into person (first_name, last_name, age) values (\'John\', \'Smith\', 20)') <-- this triggered the error
![Page 59: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/59.jpg)
Another parameters in callsdef "should persist many persons"() { given: List<Person> persons = [new Person("John", "Smith", 20), new Person("Jan", "Kowalski", 15)] when: sut.persist(persons) then: 1 * jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('John', 'Smith', 20)") 1 * jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('Jan', 'Kowalski', 15)")}
![Page 60: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/60.jpg)
Any parameter
then: 2 * jdbcTemplate.execute(_)
![Page 61: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/61.jpg)
Range of calls
then: (1..3) * jdbcTemplate.execute(_)
![Page 62: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/62.jpg)
At least one call
then: (1.._) * jdbcTemplate.execute(_)
![Page 63: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/63.jpg)
Any amount of calls
then: _ * jdbcTemplate.execute(_)
![Page 64: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/64.jpg)
Two calls of method of any mock
then: 2 * _.execute(_)
![Page 65: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/65.jpg)
Two calls of any method of mock
then: 2 * jdbcTemplate._(_)
![Page 66: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/66.jpg)
Two calls of method by regex
then: 2 * jdbcTemplate./exe.*/(_)
![Page 67: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/67.jpg)
Closure validates call
then: 2 * jdbcTemplate.execute({ String sql -> sql.endsWith("('John', 'Smith', 20)") || sql.endsWith("('Jan', 'Kowalski', 15)") })
![Page 68: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/68.jpg)
Sequential callsdef "should persist many persons in order"() { given: List<Person> persons = [new Person("John", "Smith", 20), new Person("Jan", "Kowalski", 15)] when: sut.persist(persons) then: 1 * jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('John', 'Smith', 20)") then: 1 * jdbcTemplate.execute("Insert into person (first_name, last_name, age) values ('Jan', 'Kowalski', 15)")}
![Page 69: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/69.jpg)
Define mock interactions in given block
given: jdbcTemplate = Mock(JdbcTemplate) { 2 * execute({ String sql -> sql.endsWith("('John', 'Smith', 20)") || sql.endsWith("('Jan', 'Kowalski', 15)") }) }
![Page 70: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/70.jpg)
Stub
def "should find one person"() { given: jdbcTemplate.queryForList("select first_name, last_name, age from person where last_name = ?", ["Kowalski"]) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]] expect: sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 20)]}
![Page 71: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/71.jpg)
Stub in context
given: jdbcTemplate = Stub(JdbcTemplate) { queryForList("select first_name, last_name, age from person where last_name = ?", ["Kowalski"]) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]] }
![Page 72: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/72.jpg)
Any stub parameters
def "should find many times person"() { given: jdbcTemplate.queryForList(_, _) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]] expect: sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 20)] sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 20)]}
![Page 73: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/73.jpg)
Multiple return values
def "should find many times person 2"() { given: jdbcTemplate.queryForList(_, _) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]] >> [[first_name: "Jan", last_name: "Kowalski", age: 25]] expect: sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 20)] sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 25)]}
![Page 74: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/74.jpg)
Multiple return values as list
def "should find many times person 3"() { given: jdbcTemplate.queryForList(_, _) >>> [ [[first_name: "Jan", last_name: "Kowalski", age: 20]], [[first_name: "Jan", last_name: "Kowalski", age: 15]]] expect: sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 20)] sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 15)]}
![Page 75: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/75.jpg)
Side effectsdef "should throw exception on second find"() { given: jdbcTemplate.queryForList(_, _) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]] >> { throw new DataRetrievalFailureException("Cannot retrieve data") } expect: sut.findByLastName("Kowalski") == [new Person("Jan", "Kowalski", 20)] when: sut.findByLastName("Kowalski") then: thrown(DataAccessException)}
![Page 76: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/76.jpg)
Mocking and stubbing
def "should find one person and check invocation"() { when: List result = sut.findByLastName("Kowalski") then: result == [new Person("Jan", "Kowalski", 20)] 1 * jdbcTemplate.queryForList(_, _) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]]}
![Page 77: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/77.jpg)
Any parameter list
then: 1 * jdbcTemplate.queryForList(*_) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]]
![Page 78: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/78.jpg)
Validate parameter value
then: 1 * jdbcTemplate.queryForList(_, !(["Smith"] as Object[])) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]]
![Page 79: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/79.jpg)
Validate parameter is not null
then: 1 * jdbcTemplate.queryForList(!null, _) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]]
![Page 80: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/80.jpg)
Interaction blockdef "should find one person and check invocation external with first parameter not null"() { when: List result = sut.findByLastName("Kowalski") then: result == [new Person("Jan", "Kowalski", 20)] interaction { queryForListCalledOnceWithFirstName() }}
void queryForListCalledOnceWithFirstName(){ 1 * jdbcTemplate.queryForList(!null, _) >> [[first_name: "Jan", last_name: "Kowalski", age: 20]]}
![Page 81: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/81.jpg)
SpiesList sut = Spy(ArrayList, constructorArgs: [10])
def "should use spy on list"() { given: sut.add(1) >> { callRealMethod() } sut.size() >> 10 when: sut.add(1) then: sut.size() == 10 sut.get(0) == 1}
![Page 82: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/82.jpg)
Spring
![Page 83: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/83.jpg)
Spring from configuration class@ContextConfiguration(classes = PersonContextConfiguration)class PersonContextFromClassTest extends Specification { @Autowired PersonController personController
@Autowired PersonDao personDao
//…}
![Page 84: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/84.jpg)
Spring from configuration xml@ContextConfiguration(locations = "classpath:personContext.xml")class PersonContextFromXmlTest extends Specification {
@Autowired PersonController personController
@Autowired PersonDao personDao
//…}
![Page 85: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/85.jpg)
Helper methods
![Page 86: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/86.jpg)
Without helper
def "should check person"() { when: Person result = new Person("Tom", "Smith", 20) then: result != null result.firstName == "Tom" result.lastName == "Smith" result.age == 20}
![Page 87: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/87.jpg)
Boolean helperdef "should check person with boolean helper method"() { when: Person result = new Person("Tom", "Smith", 20) then: checkPerson(result, "Tom", "Smith", 20)}boolean checkPerson(Person person, String firstName, String lastName, int age) { person != null && person.firstName == firstName && person.lastName == lastName && person.age == age}
![Page 88: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/88.jpg)
Boolean helper - outputcheckPerson(result, "Tom", "Smith", 20)| |false com.blogspot.przybyszd.spock.dto.Person(Tom, Smith, 20)
![Page 89: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/89.jpg)
Helper with assertdef "should check person with assert helper method"() { when: Person result = new Person("Tom", "Smith", 20) then: checkPersonWithAssert(result, "Tom", "Smith", 20)}void checkPersonWithAssert(Person person, String firstName, String lastName, int age) { assert person != null assert person.firstName == firstName assert person.lastName == lastName assert person.age == age}
![Page 90: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/90.jpg)
Helper with assert - outputperson.firstName == "John"| | || Tom false| 3 differences (25% similarity)| (T)o(m-)| (J)o(hn)com.blogspot.przybyszd.spock.dto.Person(Tom, Smith, 20)
![Page 91: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/91.jpg)
Withdef "should set first name, last name and age 1"() { when: Person person = new Person(firstName: "Bob", lastName: "Smith", age: 40) then: with(person) { firstName == "Bob" lastName == "Smith" age == 40 }}
![Page 92: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/92.jpg)
Annotations
![Page 93: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/93.jpg)
Ignoreclass IgnoreTest extends Specification { def "test 1"() { expect: 1 == 1 } @Ignore def "test 2"() { expect: 1 == 1 } def "test 3"() { expect: 1 == 1 }}
![Page 94: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/94.jpg)
IgnoreRestclass IgnoreRestTest extends Specification { def "test 1"() { expect: 1 == 1 } @IgnoreRest def "test 2"() { expect: 1 == 1 } def "test 3"() { expect: 1 == 1 }}
![Page 95: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/95.jpg)
IgnoreIfclass IgnoreIfTest extends Specification {
// @IgnoreIf({os.windows})// @IgnoreIf({os.linux}) @IgnoreIf({ System.getProperty("os.name").contains("Linux") }) def "test 1"() { expect: 1 == 1 }}
![Page 96: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/96.jpg)
Requiresclass RequiresTest extends Specification {
// @Requires({os.windows})// @Requires({os.linux}) @Requires({ System.getProperty("os.name").contains("windows") }) def "test 1"() { expect: 1 == 1 }}
![Page 97: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/97.jpg)
AutoCleanupclass AutoCleanupTest extends Specification {
JdbcTemplate jdbcTemplate = Mock(JdbcTemplate)
@AutoCleanup(value = "close", quiet = true) PersonDao sut = new PersonDao(jdbcTemplate)
def "test 1"() { expect: sut != null }}
![Page 98: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/98.jpg)
FailsWithclass FailsWithTest extends Specification {
@FailsWith(RuntimeException) def "test 1"() { expect: throw new RuntimeException() }}
![Page 99: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/99.jpg)
Timeout
class TimeoutTest extends Specification {
@Timeout(value = 750, unit = TimeUnit.MILLISECONDS) def "test 1"() { expect: 1 == 1 }}
![Page 100: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/100.jpg)
Title
@Title("Title annotation is tested in this specification")class TitleTest extends Specification {
def "test 1"() { expect: 1 == 1 }}
![Page 101: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/101.jpg)
Narrative
@Narrative("""Multiline narrative annotationis tested in this specification""")class NarrativeTest extends Specification {
def "test 1"() { expect: 1 == 1 }}
![Page 102: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/102.jpg)
Subject
@Subject(Person)class SubjectTest extends Specification {
@Subject Person person = new Person("John", "Smith", 21)
def "should be adult"() { expect: person.isAdult() }}
![Page 103: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/103.jpg)
Issue
class IssueTest extends Specification { @Issue(["http://example.org/mantis/view.php?
id=12345", "http://example.org/mantis/view.php?id=23"]) def "test 1"() { expect: 1 == 1 }}
![Page 104: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/104.jpg)
Extra
![Page 105: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/105.jpg)
void instead of def
void "should set first name from constructor"() { when: Person person = new Person(firstName: "Bob") then: person.firstName == "Bob"}
![Page 106: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/106.jpg)
Shoud instead of def
Should "set first name from constructor"() { when: Person person = new Person(firstName: "Bob") then: person.firstName == "Bob"}
![Page 107: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/107.jpg)
Shoud instead of def - how it works
import java.lang.Void as Should
![Page 108: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/108.jpg)
Q & A
![Page 109: 4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz](https://reader034.vdocuments.pub/reader034/viewer/2022042602/55a778fc1a28ab430a8b4866/html5/thumbnails/109.jpg)
Thank you