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

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 

Kürzlich hochgeladen (20)

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 

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