SlideShare ist ein Scribd-Unternehmen logo
1 von 52
Downloaden Sie, um offline zu lesen
@nklmish
Spock 

Testing made groovy!!
Quality is not an act, it is a habit
@nklmish
@nklmish
Agenda
What
Basic & advanced features
(hopefully enough to get you
started)
Hands on labs.
@nklmish
About me
Senior Software Engineer, Consultant and
architect around JVM technology.
Speaker
Blog - http://nklmish.me
Slideshare- http://slideshare.net/nklmish
@nklmish
What is Spock?
@nklmish
Spock…
Brings best practises(Junit, Jmock, RSpec) under one
umbrella.
Testing & specification framework
Based on Groovy
Makes testing fun (readable & compact code)
Enterprise ready
Compatible (IDEs, continuous integration services & build
tools)
Groovy goodies
@nklmish
Basic
@nklmish
Hello world spec.
Every specification must extend spock sepcification
Your specification name
class PersonSpec extends spock.lang.Specification {

def “should increment adam's annual salary by 10%"() {

given:

Person adam = new Person()

adam.setSalary(50_000)

when:

adam.grantAnnualBonus(“10%”)

then:

adam.annualSalary() == 55_000

}

}

Feature method
Spock blocks
@nklmish
Multiple assertions
Multiple assertions (if any of these condition is false then test will fail)
class PersonSpec extends spock.lang.Specification {

def “should increment adam's annual salary by 10%"() {

given:

Person adam = new Person()

adam.setSalary(50_000)

when:

adam.grantAnnualBonus(“10%”)

then:

adam.annualSalary() == 55_000

adam.isAnnualBonusGranted() //assume it returns true

!adam.isMonthlyBonusGranted() //assume it return false

}

}
@nklmish
Instance fields e.g.
Instance field
class PersonSpec extends spock.lang.Specification {

Person adam = new Person()

def “should increment adam's annual salary by 10%"() {

given:

adam.setSalary(50_000)

when:

adam.grantAnnualBonus(“10%”)

then:

adam.annualSalary() == 55_000

adam.isAnnualBonusGranted() //assume it returns true

!adam.isMonthlyBonusGranted() //assume it return false

}

}
@nklmish
Instance fields
No sharing b/w feature methods =>
Every feature method get its own
object
@nklmish
What If I want to share an
object b/w feature
methods?
@nklmish
Use @Shared
field that can be shared b/w ALL test methods
class PersonSpec extends spock.lang.Specification {

@Shared Person adam = new Person()

def “should increment adam's annual salary by 10%"() {

given:

adam.setSalary(50_000)

when:

adam.grantAnnualBonus(“10%”)

then:

adam.annualSalary() == 55_000

adam.isAnnualBonusGranted() //assume it returns true

!adam.isMonthlyBonusGranted() //assume it return false

}

}
@nklmish
Shared fields
Allows to share an object.
Useful when object creation is
expensive
@nklmish
But what about static
keyword to share an object
?
@nklmish
static keyword
Use it to share constant values for
e.g. static final FOO = 123
“@Shared” has well defined sharing
semantics over “static”
@nklmish
Spock Blocks
@nklmish
Setup/given
given -> alias for ‘setup’ -> you can
put some code that performs setup
work
Non repeatable
@nklmish
setup/given e.g.
setup block for a given test method
class LoanSpec extends spock.lang.Specification {

@Shared Cache<Integer, Loan> cache = …//



def “should find loan for a valid loan id"() {

setup:

Loan someLoan = new Loan()

cache.put(5, someLoan)

//…..

}

def “should be able to create a new loan"() {

setup:

Loan loan = new Loan()

//…..

}

}
@nklmish
cleanup
Non repeatable
Runs no matter what( i.e. runs even
if feature method has thrown an
exception)
@nklmish
cleanup e.g.
cleanup block for a given test method
class LoanSpec extends spock.lang.Specification {

@Shared Cache<Integer, Loan> cache = …//



def “should find loan for a valid loan id"() {

setup:

cache.put(5, someLoan)



cleanup:

cache.remove(5)

//…..

}

}
@nklmish
When, then & expect
when -> contains arbitrary code
then -> restricted to boolean conditions
(assertions), exceptions, interactions &
variable definitions.
expect -> restricted to boolean conditions
and variable definitions.
Note : For purely functional methods “expect”,
for side effect methods “when-then”.
@nklmish
E.g.
def “should be able to store elements into the cache” () {
when:
cache.put(5, someLoan)
then:
cache.size() == 1
}
def “should be able to count all elements from the cache” () {
expect:
cache.count() == 10
}
def “should not be able to create a loan with negative amount” () {
when:
Loan loan = new Loan(amount:-100)
then:
IllegalArgumentException ex = thrown()
ex.message == ‘Loan can only be create with amount > 0’
}
@nklmish
Assertion Helper
methoddef "should increment adam's annual salary by 10%"() {

given:

Person adam = new Person()

and:

adam.setSalary(50_000)



when:

adam.grantBonus(10)



then:

adam.annualSalary() == 55_000.0
adam.gotBonus()
adam.isHappy()
adam.isChiefExecutive()
}
@nklmish
Assertion Helper method
def "should increment adam's annual salary by 10%"() {

given:

Person adam = new Person()

and:

adam.setSalary(50_000)



when:

adam.grantBonus(10)



then:

isBonusPaid(adam, 10_00_000)
}
boolean isBonusPaid(Person person, BigDecimal expectedSalary) {

person.annualSalary() == expectedSalary &&
person.gotBonus() &&
person.isHappy() &&
person.isChiefExecutive()
}
Note: We lost descriptive error message :(
@nklmish
Assertion Helper method
def "should increment adam's annual salary by 10%"() {

given:

Person adam = new Person()

and:

adam.setSalary(50_000)


when:

adam.grantBonus(10)



then:

isBonusPaid(adam, 10_00_000)
}
void isBonusPaid(Person person,
BigDecimal expectedSalary) {

assert person.annualSalary() == expectedSalary
assert person.gotBonus()
assert person.isHappy()
assert person.isChiefExecutive()
We have our descriptive message!!
@nklmish
setup/cleanup at the
beginning/end of life cycle
@nklmish
E.g.
“quiet = true” => don't report exceptions . (default is true)
“value” => method name to invoke on
annotated object (default is ‘close’)
Note : @Autocleanup can also be used on instance fields
class LoanSpec extends spock.lang.Specification {

@AutoCleanup(quiet = true, value = “closeConnection”)

@Shared

private Database db

setupSpec() {

db.populate() //load test data 

}

def “should increment adam's annual salary by 10%"() {

setup:

cache.load()

//…..

cleanup:

cache.clear()

}

}
@nklmish
Textually rich
blocks
def "should find customer for a valid customer id"() {
given: 'an existing customer'
def customer = new Customer(firstName: "Joe", dateOfBirth: now())
when: 'we request for customer with a valid id'
def response = mockMvc.perform(get("/api/customers/1"))
then: 'we should receive client details'
1 * customerService.find(1) >> Optional.of(customer)
and:
response.status == 200
}
and label can be used at any top-level
@nklmish
Other features
@nklmish
@Requires
import spock.util.environment.OperatingSystem;

class PersonSpec extends spock.lang.Specification {

@Shared OperatingSystem os = OperatingSystem.newInstance()

@Requires({env.containsKey(“HASH_KEY_TO_AUTHENTICATE”)})

def “should verify authentication token"() {

}



@Requires({os.isWindows() || isLegacyUser() })

def “should be able to authenticate via window’s credentials"() {

}



static boolean isLegacyUser() {//…}

}

Run test ONLY if given condition(s) is/are met
@nklmish
Data pipes
class HelloDataTableSpec extends spock.lang.Specification {

def "total characters in name"() {

expect:

name.trim().size() == totalChars



where:

name << ["Joe "," doe"," hello "]

totalChars << [3, 3, 5]

}

}

Data pipes connects data variable to data provider
Data provider : Any iterable object in groovy
(including csv and sql rows)
@nklmish
Data tables, syntactic sugar
class HelloDataTableSpec extends spock.lang.Specification
{

def “should count total number of alphabets in
name"() {

expect:

name.trim().size() == totalChars



where:

name || totalChars

"Joe " || 3

" doe" || 3

" hello " || 5

}

}
@nklmish
Data tables failure
reporting
class HelloDataTableSpec extends spock.lang.Specification {

def “should count total number of alphabets in name"() {

expect:

name.trim().size() == totalChars



where:

name || totalChars

"Joe " || 3

" doe" || 3

" hello " || 50

}

}

Can we do better ?
@nklmish
Yes, using unroll
@Unroll

class HelloDataTableSpec extends spock.lang.Specification {

def “should count total number of alphabets in #name”() {

expect:

name.trim().size() == totalChars



where:

name || totalChars

"Joe " || 3

" doe" || 3

" hello " || 50

}

}
@nklmish
Ignoring tests
@Ignore
IgnoreRest
@IgnoreIf
@nklmish
@Ignore
@Ignore(“don’t run any test in this specification”)

class HelloDataTableSpec extends spock.lang.Specification
{

def “should count total number of alphabets in
name"() {

expect:

name.trim().size() == totalChars



where:

name || totalChars

"Joe " || 3

" doe" || 3

" hello " || 5

}

}
@nklmish
@Ignore
class HelloDataTableSpec extends spock.lang.Specification
{

@Ignore(“don’t run only this specific test”) 

def “should count total number of alphabets in
name"() {

expect:

name.trim().size() == totalChars



where:

name || totalChars

"Joe " || 3

" doe" || 3

" hello " || 5

}

}
@nklmish
@IgnoreRest
def “It will be ignored”() {…}
@IgnoreRest
def “It will run”() {…}
@nklmish
@IgnoreIf
def “I will run no matter what”() {…}
@IgnoreIf(os.isWindows())
def “I ll not run on windows”() {…}
@nklmish
Mocking & stubbing
@nklmish
Spock Mocking
Uses:
JDK dynamic proxies for mocking interfaces.
CGLIB proxies for mocking classes
Mock objects are lenient by default (default behaviour
can be overridden via stubbing)
Default returns values are false, 0 or null (except
Object.toString/hashCode/equals)
Note : Mock can be used for both mocking and stubbing
whereas stubs can be used only for stubbing!!!
@nklmish
Mocking E.g.
class LoanSpec extends spock.lang.Specification {
LoanManager loanManager = new LoanManager()
ValidatorManager validatorManager = Mock(ValidatorManager)
RepositoryManager repoManager = Mock(RepositoryManager)
//…
}
@nklmish
Interaction E.g.
class LoanSpec extends spock.lang.Specification {
ValidatorManager validatorManager = Mock(ValidatorManager)
RepositoryManager repoManager = Mock(RepositoryManager)
LoanManager loanManager = new LoanManager(validatorManager : validatorManager,
repositoryManager: repoManager)
def "should consult with validator manager and repository manager before saving a new loan application"() {
given:
Loan someLoan = new Loan()
when:
loanManager.save(someLoan)
then:
1 * validatorManager.validate(someLoan)
1 * repoManager.save(someLoan)
}
}
cardinality (how many method calls are expected)
target constraint (mock object)
method constraint (method you are interested in)
argument constraint (expected method argument)
@nklmish
Invocation order
class LoanSpec extends spock.lang.Specification {
ValidatorManager validatorManager = Mock(ValidatorManager)
RepositoryManager repoManager = Mock(RepositoryManager)
LoanManager loanManager = new LoanManager(validatorManager : validatorManager,
repositoryManager: repoManager)
def "should consult with validator manager and repository manager before saving a new loan application"() {
when:
loanManager.save(someLoan)
then:
1 * validatorManager.validate(someLoan)
then:
1 * repoManager.save(someLoan)
}
}
@nklmish
Detecting Mock Obj
class LoanSpec extends spock.lang.Specification {
ValidatorManager validatorManager = Mock(ValidatorManager)
RepositoryManager repoManager = Mock(RepositoryManager)
LoanManager loanManager = new LoanManager(validatorManager : validatorManager,
repositoryManager: repoManager)
def "should consult with validator manager before saving a new loan application"() {
when:
loanManager.save(someLoan)
then:
1 * validatorManager.validate(someLoan)
new MockDetector().isMock(validatorManager)
}
}
You can get more info using MockDetector, like name, type, etc
@nklmish
Stub
When you are ONLY interested in
returning some value in respond to
particular method call OR want to
perform side effect.
@nklmish
Stubbing
ValidatorManager validatorManager = Stub(ValidatorManager)
def setup() {
validatorManager.validate(_) >> true
}
}
Note: this will always return true whenever
validatorManager.validate() is invoked
@nklmish
Stubbing, return list
of values
ValidatorManager validatorManager = Stub(ValidatorManager)
def setup() {
validatorManager.validate >> [true,false,true]
}
}
translates to: return true for first invocation, false
for second and true for all other invocations
@nklmish
Stubbing, throw exception
+ chaining responses
ValidatorManager validatorManager = Stub(ValidatorManager)
def setup() {
validatorManager.validate >> [true,false] >> {throw new
RuntimeException()} >> [true]
}
}
translates to: return true for first invocation, false for
second and throw exception for third and return true for
all other invocations
@nklmish
Summary
Builtin mocking framework
Descriptive failure message
Readable tests
Groovy goodies
Extensible
@nklmish
Lab Exercises
@nklmish
Thank you !

Weitere ähnliche Inhalte

Was ist angesagt?

Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128PrinceGuru MS
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perlgarux
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Jeff Carouth
 
Javascript the New Parts v2
Javascript the New Parts v2Javascript the New Parts v2
Javascript the New Parts v2Federico Galassi
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GParsPaul King
 
Haskell is Not For Production and Other Tales
Haskell is Not For Production and Other TalesHaskell is Not For Production and Other Tales
Haskell is Not For Production and Other TalesKatie Ots
 
Pursuing the Strong, Not So Silent Type: A Haskell Story
Pursuing the Strong, Not So Silent Type: A Haskell StoryPursuing the Strong, Not So Silent Type: A Haskell Story
Pursuing the Strong, Not So Silent Type: A Haskell StoryKatie Ots
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationAttila Balazs
 
Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)Bozhidar Batsov
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPMariano Iglesias
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Kang-min Liu
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I thinkWim Godden
 
Spock Framework - Slidecast
Spock Framework - SlidecastSpock Framework - Slidecast
Spock Framework - SlidecastDaniel Kolman
 
Proposal for xSpep BDD Framework for PHP
Proposal for xSpep BDD Framework for PHPProposal for xSpep BDD Framework for PHP
Proposal for xSpep BDD Framework for PHPYuya Takeyama
 
Smarter Testing With Spock
Smarter Testing With SpockSmarter Testing With Spock
Smarter Testing With SpockIT Weekend
 
Beyond javascript using the features of tomorrow
Beyond javascript   using the features of tomorrowBeyond javascript   using the features of tomorrow
Beyond javascript using the features of tomorrowAlexander Varwijk
 

Was ist angesagt? (20)

Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128
 
Descobrindo a linguagem Perl
Descobrindo a linguagem PerlDescobrindo a linguagem Perl
Descobrindo a linguagem Perl
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Javascript the New Parts v2
Javascript the New Parts v2Javascript the New Parts v2
Javascript the New Parts v2
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GPars
 
Haskell is Not For Production and Other Tales
Haskell is Not For Production and Other TalesHaskell is Not For Production and Other Tales
Haskell is Not For Production and Other Tales
 
Pursuing the Strong, Not So Silent Type: A Haskell Story
Pursuing the Strong, Not So Silent Type: A Haskell StoryPursuing the Strong, Not So Silent Type: A Haskell Story
Pursuing the Strong, Not So Silent Type: A Haskell Story
 
Barely Legal Xxx Perl Presentation
Barely Legal Xxx Perl PresentationBarely Legal Xxx Perl Presentation
Barely Legal Xxx Perl Presentation
 
Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)Модерни езици за програмиране за JVM (2011)
Модерни езици за програмиране за JVM (2011)
 
Going crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHPGoing crazy with Node.JS and CakePHP
Going crazy with Node.JS and CakePHP
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Perl object ?
Perl object ?Perl object ?
Perl object ?
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
Spock Framework - Slidecast
Spock Framework - SlidecastSpock Framework - Slidecast
Spock Framework - Slidecast
 
Proposal for xSpep BDD Framework for PHP
Proposal for xSpep BDD Framework for PHPProposal for xSpep BDD Framework for PHP
Proposal for xSpep BDD Framework for PHP
 
Smarter Testing With Spock
Smarter Testing With SpockSmarter Testing With Spock
Smarter Testing With Spock
 
Beyond javascript using the features of tomorrow
Beyond javascript   using the features of tomorrowBeyond javascript   using the features of tomorrow
Beyond javascript using the features of tomorrow
 
Fatc
FatcFatc
Fatc
 
Ruby
RubyRuby
Ruby
 
Java and xml
Java and xmlJava and xml
Java and xml
 

Ähnlich wie Spock

Getting started with ES6
Getting started with ES6Getting started with ES6
Getting started with ES6Nitay Neeman
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescriptDavid Furber
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and ProsperKen Kousen
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebChristian Baranowski
 
Nosql hands on handout 04
Nosql hands on handout 04Nosql hands on handout 04
Nosql hands on handout 04Krishna Sankar
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl TechniquesDave Cross
 
Curso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: ShouldaCurso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: ShouldaAlberto Perdomo
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quoIvano Pagano
 
Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Colin Oakley
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestHoward Lewis Ship
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairMark
 
All you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsAll you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsOluwaleke Fakorede
 
node.js Module Development
node.js Module Developmentnode.js Module Development
node.js Module DevelopmentJay Harris
 
Django in the Office: Get Your Admin for Nothing and Your SQL for Free
Django in the Office: Get Your Admin for Nothing and Your SQL for FreeDjango in the Office: Get Your Admin for Nothing and Your SQL for Free
Django in the Office: Get Your Admin for Nothing and Your SQL for FreeHarvard Web Working Group
 

Ähnlich wie Spock (20)

Spock Framework
Spock FrameworkSpock Framework
Spock Framework
 
Getting started with ES6
Getting started with ES6Getting started with ES6
Getting started with ES6
 
Ruby Basics
Ruby BasicsRuby Basics
Ruby Basics
 
Real life-coffeescript
Real life-coffeescriptReal life-coffeescript
Real life-coffeescript
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
 
Nosql hands on handout 04
Nosql hands on handout 04Nosql hands on handout 04
Nosql hands on handout 04
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
Curso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: ShouldaCurso TDD Ruby on Rails #05: Shoulda
Curso TDD Ruby on Rails #05: Shoulda
 
Questioning the status quo
Questioning the status quoQuestioning the status quo
Questioning the status quo
 
Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017Testing most things in JavaScript - LeedsJS 31/05/2017
Testing most things in JavaScript - LeedsJS 31/05/2017
 
Angular Schematics
Angular SchematicsAngular Schematics
Angular Schematics
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To Test
 
Unfiltered Unveiled
Unfiltered UnveiledUnfiltered Unveiled
Unfiltered Unveiled
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
CoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love AffairCoffeeScript - A Rubyist's Love Affair
CoffeeScript - A Rubyist's Love Affair
 
All you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsAll you need to know about JavaScript Functions
All you need to know about JavaScript Functions
 
Go testdeep
Go testdeepGo testdeep
Go testdeep
 
node.js Module Development
node.js Module Developmentnode.js Module Development
node.js Module Development
 
Django in the Office: Get Your Admin for Nothing and Your SQL for Free
Django in the Office: Get Your Admin for Nothing and Your SQL for FreeDjango in the Office: Get Your Admin for Nothing and Your SQL for Free
Django in the Office: Get Your Admin for Nothing and Your SQL for Free
 

Mehr von nklmish

Demystifying Kafka
Demystifying KafkaDemystifying Kafka
Demystifying Kafkanklmish
 
Scaling CQRS in theory, practice, and reality
Scaling CQRS in theory, practice, and realityScaling CQRS in theory, practice, and reality
Scaling CQRS in theory, practice, and realitynklmish
 
CQRS and EventSourcing with Spring & Axon
CQRS and EventSourcing with Spring & AxonCQRS and EventSourcing with Spring & Axon
CQRS and EventSourcing with Spring & Axonnklmish
 
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOXnklmish
 
Kotlin boost yourproductivity
Kotlin boost yourproductivityKotlin boost yourproductivity
Kotlin boost yourproductivitynklmish
 
Distributed tracing - get a grasp on your production
Distributed tracing - get a grasp on your productionDistributed tracing - get a grasp on your production
Distributed tracing - get a grasp on your productionnklmish
 
Microservice no fluff, the REAL stuff
Microservice no fluff, the REAL stuffMicroservice no fluff, the REAL stuff
Microservice no fluff, the REAL stuffnklmish
 
Mongo - an intermediate introduction
Mongo - an intermediate introductionMongo - an intermediate introduction
Mongo - an intermediate introductionnklmish
 
Detailed Introduction To Docker
Detailed Introduction To DockerDetailed Introduction To Docker
Detailed Introduction To Dockernklmish
 

Mehr von nklmish (10)

Demystifying Kafka
Demystifying KafkaDemystifying Kafka
Demystifying Kafka
 
Scaling CQRS in theory, practice, and reality
Scaling CQRS in theory, practice, and realityScaling CQRS in theory, practice, and reality
Scaling CQRS in theory, practice, and reality
 
CQRS and EventSourcing with Spring & Axon
CQRS and EventSourcing with Spring & AxonCQRS and EventSourcing with Spring & Axon
CQRS and EventSourcing with Spring & Axon
 
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
(SPRING)KAFKA - ONE MORE ARSENAL IN A DISTRIBUTED TOOLBOX
 
Kotlin boost yourproductivity
Kotlin boost yourproductivityKotlin boost yourproductivity
Kotlin boost yourproductivity
 
Distributed tracing - get a grasp on your production
Distributed tracing - get a grasp on your productionDistributed tracing - get a grasp on your production
Distributed tracing - get a grasp on your production
 
Microservice no fluff, the REAL stuff
Microservice no fluff, the REAL stuffMicroservice no fluff, the REAL stuff
Microservice no fluff, the REAL stuff
 
Neo4J
Neo4JNeo4J
Neo4J
 
Mongo - an intermediate introduction
Mongo - an intermediate introductionMongo - an intermediate introduction
Mongo - an intermediate introduction
 
Detailed Introduction To Docker
Detailed Introduction To DockerDetailed Introduction To Docker
Detailed Introduction To Docker
 

Kürzlich hochgeladen

Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 

Kürzlich hochgeladen (20)

Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 

Spock

  • 1. @nklmish Spock 
 Testing made groovy!! Quality is not an act, it is a habit @nklmish
  • 2. @nklmish Agenda What Basic & advanced features (hopefully enough to get you started) Hands on labs.
  • 3. @nklmish About me Senior Software Engineer, Consultant and architect around JVM technology. Speaker Blog - http://nklmish.me Slideshare- http://slideshare.net/nklmish
  • 5. @nklmish Spock… Brings best practises(Junit, Jmock, RSpec) under one umbrella. Testing & specification framework Based on Groovy Makes testing fun (readable & compact code) Enterprise ready Compatible (IDEs, continuous integration services & build tools) Groovy goodies
  • 7. @nklmish Hello world spec. Every specification must extend spock sepcification Your specification name class PersonSpec extends spock.lang.Specification {
 def “should increment adam's annual salary by 10%"() {
 given:
 Person adam = new Person()
 adam.setSalary(50_000)
 when:
 adam.grantAnnualBonus(“10%”) then: adam.annualSalary() == 55_000
 }
 } Feature method Spock blocks
  • 8. @nklmish Multiple assertions Multiple assertions (if any of these condition is false then test will fail) class PersonSpec extends spock.lang.Specification {
 def “should increment adam's annual salary by 10%"() {
 given:
 Person adam = new Person()
 adam.setSalary(50_000)
 when:
 adam.grantAnnualBonus(“10%”) then: adam.annualSalary() == 55_000 adam.isAnnualBonusGranted() //assume it returns true !adam.isMonthlyBonusGranted() //assume it return false
 }
 }
  • 9. @nklmish Instance fields e.g. Instance field class PersonSpec extends spock.lang.Specification { Person adam = new Person()
 def “should increment adam's annual salary by 10%"() {
 given:
 adam.setSalary(50_000)
 when:
 adam.grantAnnualBonus(“10%”) then: adam.annualSalary() == 55_000 adam.isAnnualBonusGranted() //assume it returns true !adam.isMonthlyBonusGranted() //assume it return false
 }
 }
  • 10. @nklmish Instance fields No sharing b/w feature methods => Every feature method get its own object
  • 11. @nklmish What If I want to share an object b/w feature methods?
  • 12. @nklmish Use @Shared field that can be shared b/w ALL test methods class PersonSpec extends spock.lang.Specification { @Shared Person adam = new Person()
 def “should increment adam's annual salary by 10%"() {
 given:
 adam.setSalary(50_000)
 when:
 adam.grantAnnualBonus(“10%”) then: adam.annualSalary() == 55_000 adam.isAnnualBonusGranted() //assume it returns true !adam.isMonthlyBonusGranted() //assume it return false
 }
 }
  • 13. @nklmish Shared fields Allows to share an object. Useful when object creation is expensive
  • 14. @nklmish But what about static keyword to share an object ?
  • 15. @nklmish static keyword Use it to share constant values for e.g. static final FOO = 123 “@Shared” has well defined sharing semantics over “static”
  • 17. @nklmish Setup/given given -> alias for ‘setup’ -> you can put some code that performs setup work Non repeatable
  • 18. @nklmish setup/given e.g. setup block for a given test method class LoanSpec extends spock.lang.Specification { @Shared Cache<Integer, Loan> cache = …//
 def “should find loan for a valid loan id"() {
 setup: Loan someLoan = new Loan()
 cache.put(5, someLoan) //….. } def “should be able to create a new loan"() {
 setup:
 Loan loan = new Loan() //….. }
 }
  • 19. @nklmish cleanup Non repeatable Runs no matter what( i.e. runs even if feature method has thrown an exception)
  • 20. @nklmish cleanup e.g. cleanup block for a given test method class LoanSpec extends spock.lang.Specification { @Shared Cache<Integer, Loan> cache = …//
 def “should find loan for a valid loan id"() { setup: cache.put(5, someLoan) 
 cleanup:
 cache.remove(5) //….. }
 }
  • 21. @nklmish When, then & expect when -> contains arbitrary code then -> restricted to boolean conditions (assertions), exceptions, interactions & variable definitions. expect -> restricted to boolean conditions and variable definitions. Note : For purely functional methods “expect”, for side effect methods “when-then”.
  • 22. @nklmish E.g. def “should be able to store elements into the cache” () { when: cache.put(5, someLoan) then: cache.size() == 1 } def “should be able to count all elements from the cache” () { expect: cache.count() == 10 } def “should not be able to create a loan with negative amount” () { when: Loan loan = new Loan(amount:-100) then: IllegalArgumentException ex = thrown() ex.message == ‘Loan can only be create with amount > 0’ }
  • 23. @nklmish Assertion Helper methoddef "should increment adam's annual salary by 10%"() {
 given:
 Person adam = new Person()
 and:
 adam.setSalary(50_000)
 
 when:
 adam.grantBonus(10)
 
 then:
 adam.annualSalary() == 55_000.0 adam.gotBonus() adam.isHappy() adam.isChiefExecutive() }
  • 24. @nklmish Assertion Helper method def "should increment adam's annual salary by 10%"() {
 given:
 Person adam = new Person()
 and:
 adam.setSalary(50_000)
 
 when:
 adam.grantBonus(10)
 
 then:
 isBonusPaid(adam, 10_00_000) } boolean isBonusPaid(Person person, BigDecimal expectedSalary) {
 person.annualSalary() == expectedSalary && person.gotBonus() && person.isHappy() && person.isChiefExecutive() } Note: We lost descriptive error message :(
  • 25. @nklmish Assertion Helper method def "should increment adam's annual salary by 10%"() {
 given:
 Person adam = new Person()
 and:
 adam.setSalary(50_000) 
 when:
 adam.grantBonus(10)
 
 then:
 isBonusPaid(adam, 10_00_000) } void isBonusPaid(Person person, BigDecimal expectedSalary) {
 assert person.annualSalary() == expectedSalary assert person.gotBonus() assert person.isHappy() assert person.isChiefExecutive() We have our descriptive message!!
  • 27. @nklmish E.g. “quiet = true” => don't report exceptions . (default is true) “value” => method name to invoke on annotated object (default is ‘close’) Note : @Autocleanup can also be used on instance fields class LoanSpec extends spock.lang.Specification { @AutoCleanup(quiet = true, value = “closeConnection”) @Shared private Database db setupSpec() { db.populate() //load test data } def “should increment adam's annual salary by 10%"() {
 setup:
 cache.load() //….. cleanup: cache.clear()
 }
 }
  • 28. @nklmish Textually rich blocks def "should find customer for a valid customer id"() { given: 'an existing customer' def customer = new Customer(firstName: "Joe", dateOfBirth: now()) when: 'we request for customer with a valid id' def response = mockMvc.perform(get("/api/customers/1")) then: 'we should receive client details' 1 * customerService.find(1) >> Optional.of(customer) and: response.status == 200 } and label can be used at any top-level
  • 30. @nklmish @Requires import spock.util.environment.OperatingSystem; class PersonSpec extends spock.lang.Specification { @Shared OperatingSystem os = OperatingSystem.newInstance()
 @Requires({env.containsKey(“HASH_KEY_TO_AUTHENTICATE”)}) def “should verify authentication token"() {
 } 
 @Requires({os.isWindows() || isLegacyUser() }) def “should be able to authenticate via window’s credentials"() {
 } static boolean isLegacyUser() {//…}
 } Run test ONLY if given condition(s) is/are met
  • 31. @nklmish Data pipes class HelloDataTableSpec extends spock.lang.Specification {
 def "total characters in name"() {
 expect:
 name.trim().size() == totalChars
 
 where:
 name << ["Joe "," doe"," hello "]
 totalChars << [3, 3, 5]
 } } Data pipes connects data variable to data provider Data provider : Any iterable object in groovy (including csv and sql rows)
  • 32. @nklmish Data tables, syntactic sugar class HelloDataTableSpec extends spock.lang.Specification {
 def “should count total number of alphabets in name"() {
 expect:
 name.trim().size() == totalChars
 
 where:
 name || totalChars
 "Joe " || 3
 " doe" || 3
 " hello " || 5
 }
 }
  • 33. @nklmish Data tables failure reporting class HelloDataTableSpec extends spock.lang.Specification {
 def “should count total number of alphabets in name"() {
 expect:
 name.trim().size() == totalChars
 
 where:
 name || totalChars
 "Joe " || 3
 " doe" || 3
 " hello " || 50
 }
 } Can we do better ?
  • 34. @nklmish Yes, using unroll @Unroll class HelloDataTableSpec extends spock.lang.Specification {
 def “should count total number of alphabets in #name”() {
 expect:
 name.trim().size() == totalChars
 
 where:
 name || totalChars
 "Joe " || 3
 " doe" || 3
 " hello " || 50
 }
 }
  • 36. @nklmish @Ignore @Ignore(“don’t run any test in this specification”) class HelloDataTableSpec extends spock.lang.Specification { def “should count total number of alphabets in name"() {
 expect:
 name.trim().size() == totalChars
 
 where:
 name || totalChars
 "Joe " || 3
 " doe" || 3
 " hello " || 5
 }
 }
  • 37. @nklmish @Ignore class HelloDataTableSpec extends spock.lang.Specification {
 @Ignore(“don’t run only this specific test”) def “should count total number of alphabets in name"() {
 expect:
 name.trim().size() == totalChars
 
 where:
 name || totalChars
 "Joe " || 3
 " doe" || 3
 " hello " || 5
 }
 }
  • 38. @nklmish @IgnoreRest def “It will be ignored”() {…} @IgnoreRest def “It will run”() {…}
  • 39. @nklmish @IgnoreIf def “I will run no matter what”() {…} @IgnoreIf(os.isWindows()) def “I ll not run on windows”() {…}
  • 41. @nklmish Spock Mocking Uses: JDK dynamic proxies for mocking interfaces. CGLIB proxies for mocking classes Mock objects are lenient by default (default behaviour can be overridden via stubbing) Default returns values are false, 0 or null (except Object.toString/hashCode/equals) Note : Mock can be used for both mocking and stubbing whereas stubs can be used only for stubbing!!!
  • 42. @nklmish Mocking E.g. class LoanSpec extends spock.lang.Specification { LoanManager loanManager = new LoanManager() ValidatorManager validatorManager = Mock(ValidatorManager) RepositoryManager repoManager = Mock(RepositoryManager) //… }
  • 43. @nklmish Interaction E.g. class LoanSpec extends spock.lang.Specification { ValidatorManager validatorManager = Mock(ValidatorManager) RepositoryManager repoManager = Mock(RepositoryManager) LoanManager loanManager = new LoanManager(validatorManager : validatorManager, repositoryManager: repoManager) def "should consult with validator manager and repository manager before saving a new loan application"() { given: Loan someLoan = new Loan() when: loanManager.save(someLoan) then: 1 * validatorManager.validate(someLoan) 1 * repoManager.save(someLoan) } } cardinality (how many method calls are expected) target constraint (mock object) method constraint (method you are interested in) argument constraint (expected method argument)
  • 44. @nklmish Invocation order class LoanSpec extends spock.lang.Specification { ValidatorManager validatorManager = Mock(ValidatorManager) RepositoryManager repoManager = Mock(RepositoryManager) LoanManager loanManager = new LoanManager(validatorManager : validatorManager, repositoryManager: repoManager) def "should consult with validator manager and repository manager before saving a new loan application"() { when: loanManager.save(someLoan) then: 1 * validatorManager.validate(someLoan) then: 1 * repoManager.save(someLoan) } }
  • 45. @nklmish Detecting Mock Obj class LoanSpec extends spock.lang.Specification { ValidatorManager validatorManager = Mock(ValidatorManager) RepositoryManager repoManager = Mock(RepositoryManager) LoanManager loanManager = new LoanManager(validatorManager : validatorManager, repositoryManager: repoManager) def "should consult with validator manager before saving a new loan application"() { when: loanManager.save(someLoan) then: 1 * validatorManager.validate(someLoan) new MockDetector().isMock(validatorManager) } } You can get more info using MockDetector, like name, type, etc
  • 46. @nklmish Stub When you are ONLY interested in returning some value in respond to particular method call OR want to perform side effect.
  • 47. @nklmish Stubbing ValidatorManager validatorManager = Stub(ValidatorManager) def setup() { validatorManager.validate(_) >> true } } Note: this will always return true whenever validatorManager.validate() is invoked
  • 48. @nklmish Stubbing, return list of values ValidatorManager validatorManager = Stub(ValidatorManager) def setup() { validatorManager.validate >> [true,false,true] } } translates to: return true for first invocation, false for second and true for all other invocations
  • 49. @nklmish Stubbing, throw exception + chaining responses ValidatorManager validatorManager = Stub(ValidatorManager) def setup() { validatorManager.validate >> [true,false] >> {throw new RuntimeException()} >> [true] } } translates to: return true for first invocation, false for second and throw exception for third and return true for all other invocations
  • 50. @nklmish Summary Builtin mocking framework Descriptive failure message Readable tests Groovy goodies Extensible