рдореЙрдХ 3 рд╢рдХреНрддрд┐рд╢рд╛рд▓реА (рд▓реЗрдХрд┐рди рд╕рд╛рд░ рдореЗрдВ рдЕрд▓рдЧ) рдЙрдкрдХрд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд▓реЗрдЦрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддрд╛ рд╣реИ: рдореЙрдХ, рд╕реНрдЯрдм рдФрд░ рд╕реНрдкрд╛рдИред
рдХрд╛рдлреА рдмрд╛рд░, рдХреЛрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рд╕реЗ рдмрд╛рд╣рд░реА рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬрд┐рд╕реЗ рдирд┐рд░реНрднрд░рддрд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ (рдореВрд▓ рд▓реЗрдЦ рд╕рд╣рдпреЛрдЧреА рд╢рдмреНрдж рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд░реВрд╕реА рднрд╛рд╖рд╛ рдХреЗ рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ рдмрд╣реБрдд рдЖрдо рдирд╣реАрдВ рд╣реИ)ред
рдореЙрдХ, рд╕реНрдЯрдм рдФрд░ рд╕реНрдкрд╛рдИ рдХреЗ рд╡рд┐рднрд┐рдиреНрди рд╡реЗрд░рд┐рдПрдВрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯ рдХреЛ рдЕрдХреНрд╕рд░ рдПрдХ рдЕрд▓рдЧ-рдерд▓рдЧ рд╡рд░реНрдЧ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рддреЛ рдкрд░реАрдХреНрд╖рдг рдЕрдзрд┐рдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдФрд░ рдХрдо рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реЛрдЧреА рдХреНрдпреЛрдВрдХрд┐ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛрдб рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрддрд╛ рд╣реИред
рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдЖрдВрддрд░рд┐рдХ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рдмрджрд▓рддреЗ рд╕рдордп рдЗрд╕ рддрд░рд╣ рдХреЗ рдЕрд▓рдЧ-рдерд▓рдЧ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рд╕рдорд╕реНрдпрд╛ рдХрдо рд╣реЛрддреА рд╣реИред
рдЕрдиреБрд╡рд╛рджрдХ рд╕реЗ: рд╣рд░ рдмрд╛рд░ рдЬрдм рдореИрдВ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП Spock рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рддреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдЪреБрдирддреЗ рд╕рдордп рдореИрдВ рдПрдХ рдЧрд▓рддреА рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореЛрдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрдВрддреНрд░ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдХрдо рд╕рдВрднрд╡ рдзреЛрдЦрд╛ рд╢реАрдЯ рд╣реИред
рдЯреАрдПрд▓, рдбреЙ
mocks
рдореЙрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
- рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдФрд░ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдмреАрдЪ рдЕрдиреБрдмрдВрдз рдХреА рдЬрд╛рдБрдЪ
- рдЙрд╕ рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЬрд╛рдБрдЪрдирд╛ рдХрдИ рдмрд╛рд░ рд╕рд╣реА рд╕рдВрдЦреНрдпрд╛ рдХрд╣рд▓рд╛рддрд╛ рд╣реИ
- рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рд╕рддреНрдпрд╛рдкрди рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдирд┐рд░реНрднрд░рддрд╛ рдХреЛрдб рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ
рд╕реНрдЯрдмреНрд╕
рд╕реНрдЯрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
- рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреЙрд▓ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рджрд╛рди рдХрд░рдирд╛
- рдирд┐рд░реНрднрд░рддрд╛ рд╕реЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░рдирд╛, рдЬреИрд╕реЗ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдлреЗрдВрдХрдирд╛
рдЬрд╛рд╕реВрд╕
рдбрд░ рдЬрд╛рд╕реВрд╕ред рдЬреИрд╕рд╛ рдХрд┐ рд╕реНрдкреЙрдХ рдкреНрд░рд▓реЗрдЦрди рдХрд╣рддрд╛ рд╣реИ:
рдЗрд╕ рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рджреЛ рдмрд╛рд░ рд╕реЛрдЪреЗрдВред рд╢рд╛рдпрдж рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╕рдорд╛рдзрд╛рди рдХреЛ рдлрд┐рд░ рд╕реЗ рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рдкреБрдирд░реНрдЧрдард┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд┐рд░реНрдл рдЗрддрдирд╛ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдРрд╕реА рд╕реНрдерд┐рддрд┐рдпрд╛рдВ рд╣реЛрддреА рд╣реИрдВ рдЬрдм рд╣рдореЗрдВ рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╣реЛрддрд╛ рд╣реИред рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХреЛ рдореЙрдм рдФрд░ рд╕реНрдЯрдмреНрд╕ рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдпрд╛ рдЕрд╕рдВрднрд╡ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХреЗрд╡рд▓ рдПрдХ рд╕рдорд╛рдзрд╛рди рд╣реИ: рд╕реНрдкрд╛рдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдпрд╣ рдмреЗрд╣рддрд░ рд╣реИ рдХрд┐ рд╕реНрдкрд╛рдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХреЛ рдХрд╡рд░ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЬрд┐рд╕рдореЗрдВ рд╡рд┐рд░рд╛рд╕рдд рдкрд░реАрдХреНрд╖рдг рдмрд┐рд▓реНрдХреБрд▓ рди рд╣реЛрдВред
рдЬрд╛рд╕реВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
- рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг
- рдЙрд╕ рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЬрд╛рдБрдЪрдирд╛ рдХрдИ рдмрд╛рд░ рд╕рд╣реА рд╕рдВрдЦреНрдпрд╛ рдХрд╣рд▓рд╛рддрд╛ рд╣реИ
- рдкрд╛рд░рд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдорд╛рдиреНрдпрддрд╛
- рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдирд┐рд░реНрднрд░рддрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рджрд╛рди рдХрд░рдирд╛
- рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░рдирд╛
mocks
рдореЛрдХреНрд╕рд╕ рдХреА рд╕рд╛рд░реА рд╢рдХреНрддрд┐ рддрдм рдкреНрд░рдХрдЯ рд╣реЛрддреА рд╣реИ рдЬрдм рдПрдХ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯ рдХрд╛ рдХрд╛рд░реНрдп рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдФрд░ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдмреАрдЪ рдЕрдиреБрдмрдВрдз рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣реЛрддрд╛ рд╣реИред рдЖрдЗрдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ, рдЬрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ FooController
рдирд┐рдпрдВрддреНрд░рдХ рд╣реИ рдЬреЛ FooService
рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ FooService
рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░рддрд╛ рд╣реИред
FooController.groovy
package com.mycompany.myapp import groovy.transform.CompileStatic @CompileStatic class FooController { FooService fooService def doSomething() { render fooService.doSomething("Sally") } }
FooService.groovy
package com.mycompany.myapp import groovy.transform.CompileStatic @CompileStatic class FooService { String doSomething(String name) { "Hi ${name}, FooService did something" } }
рдЗрд╕ рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ, рд╣рдо рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬреЛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдЧрд╛:
FooController
рдФрд░ FooService
рдмреАрдЪ рдЕрдиреБрдмрдВрдзFooService.doSomething(name)
рдХреЛ рд╕рдордп рдХреА рд╕рд╣реА рд╕рдВрдЦреНрдпрд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИFooService.doSomething(name)
рдХреЛ рд╕рд╣реА рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ
рдкрд░реАрдХреНрд╖рдг рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
MockSpec.groovy
package com.mycompany.myapp import grails.testing.web.controllers.ControllerUnitTest import spock.lang.Specification class MockSpec extends Specification implements ControllerUnitTest<FooController> { void "Mock FooService"() { given: " " def fooService = Mock(FooService) and: " " controller.fooService = fooService when: " " controller.doSomething() then: " " 1 * fooService.doSomething("Sally") and: " '' - 'null'" response.text == null.toString() } }
рдЙрдкрд░реЛрдХреНрдд рдкрд░реАрдХреНрд╖рдг рдПрдХ рд╕реЗрд╡рд╛ рдирдХрд▓реА рдмрдирд╛рддрд╛ рд╣реИ:
def fooService = Mock(FooService)
рдкрд░реАрдХреНрд╖рдг рдпрд╣ рднреА рдЬрд╛рдВрдЪрддрд╛ рд╣реИ рдХрд┐ FooService.doSomething(name)
рдХреЛ рдПрдХ рдмрд╛рд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдкрд╛рд░рд┐рдд рдкреИрд░рд╛рдореАрдЯрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ "Sally"
рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИред
1 * fooService.doSomething("Sally")
рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб 4 рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ:
FooService
рд▓рд┐рдП рдирдХрд▓реА рдмрдирд╛рддрд╛ рд╣реИ- рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐
FooService.doSomething(String name)
рдХреЛ рдПрдХ рдмрд╛рд░ String
рдкреИрд░рд╛рдореАрдЯрд░ рдФрд░ рдорд╛рди "Sally"
FooService.doSomething(String name)
"Sally"
рд╕рд╛рде рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ - рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЬрдЧрд╣, рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдХреЛ рдЕрд▓рдЧ рдХрд░рддрд╛ рд╣реИ
рд╕реНрдЯрдмреНрд╕
рдХреНрдпрд╛ рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ? рдХреНрдпрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рддреЗ рд╕рдордп рдкрд░реАрдХреНрд╖рдг рдХреЗ рддрд╣рдд рдХреЛрдб рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ? рдкрд░реАрдХреНрд╖рдг рдХреЗ рддрд╣рдд рдХреЛрдб рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдЗрдирдкреБрдЯ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рдХреЗ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ?
рдпрджрд┐ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдП рдЧрдП рдХреЛрдб рдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рд╕реНрдЯрдмреНрд╕ (рд╕реНрдЯрдм) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЖрдЗрдП FooController
рдФрд░ FooService
рд╕рд╛рде рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг FooController
рдФрд░ рд╕реНрдЯрдмреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВред
FooController.groovy
package com.mycompany.myapp import groovy.transform.CompileStatic @CompileStatic class FooController { FooService fooService def doSomething() { render fooService.doSomething("Sally") } }
FooService.groovy
package com.mycompany.myapp import groovy.transform.CompileStatic @CompileStatic class FooService { String doSomething(String name) { "Hi ${name}, FooService did something" } }
рдЯреЗрд╕реНрдЯ рдХреЛрдб:
StubSpec.groovy
package com.mycompany.myapp import grails.testing.web.controllers.ControllerUnitTest import spock.lang.Specification class StubSpec extends Specification implements ControllerUnitTest<FooController> { void "Stub FooService"() { given: " " def fooService = Stub(FooService) { doSomething(_) >> "Stub did something" } and: " " controller.fooService = fooService when: " " controller.doSomething() then: " "
рдЖрдк рдЗрд╕ рддрд░рд╣ рдПрдХ рд╕реНрдЯрдм рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:
def fooService = Stub(FooService) { doSomething(_) >> "Stub did something" }
рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб 4 рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ:
- рдПрдХ
FooService
рдмрдирд╛рддрд╛ рд╣реИ - рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐
FooService.doSomething(String name)
рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдЧрд╛ "Stub did something"
рдкреИрд░рд╛рдореАрдЯрд░ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ (рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ _
рдЪрд░рд┐рддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛) - рдПрдХ рд╕реНрдЯрдм рдХреЗ рд╕рд╛рде рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЬрдЧрд╣, рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдХреЛ рдЕрд▓рдЧ рдХрд░рддрд╛ рд╣реИ
рдЬрд╛рд╕реВрд╕
рдХреГрдкрдпрд╛ рдЗрд╕ рдЕрдиреБрднрд╛рдЧ рдХреЛ рди рдкрдврд╝реЗрдВред
рди рджреЗрдЦреЛред
рдЕрдЧрд▓реЗ рдПрдХ рдкрд░ рдЫреЛрдбрд╝ рджреЗрдВред
рдЕрднреА рднреА рдкрдврд╝ рд░рд╣реЗ рд╣реИрдВ? рддреЛ рдареАрдХ рд╣реИ, рдареАрдХ рд╣реИ, рдЪрд▓реЛ рдЬрд╛рд╕реВрд╕ рдХреЗ рд╕рд╛рде рд╕реМрджрд╛ рдХрд░рддреЗ рд╣реИрдВред
рд╕реНрдкрд╛рдИ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рди рдХрд░реЗрдВред рдЬреИрд╕рд╛ рдХрд┐ рд╕реНрдкреЙрдХ рдкреНрд░рд▓реЗрдЦрди рдХрд╣рддрд╛ рд╣реИ:
рдЗрд╕ рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рджреЛ рдмрд╛рд░ рд╕реЛрдЪреЗрдВред рд╢рд╛рдпрдж рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╕рдорд╛рдзрд╛рди рдХреЛ рдлрд┐рд░ рд╕реЗ рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рдкреБрдирд░реНрдЧрдард┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдРрд╕реА рд╕реНрдерд┐рддрд┐рдпрд╛рдВ рд╣реИрдВ рдЬрдм рд╣рдореЗрдВ рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдореЙрдм рдпрд╛ рд╕реНрдЯрдмреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЬрд╛рд╕реВрд╕ рдПрдХрдорд╛рддреНрд░ рд╡реНрдпрд╡рд╣рд╛рд░реНрдп рд╡рд┐рдХрд▓реНрдк рдмрдирд╛ рд╣реБрдЖ рд╣реИред
рдЬрд╛рд╕реВрд╕ рдореЛрдХ рдпрд╛ рд╕реНрдЯрдмреНрд╕ рд╕реЗ рдЕрд▓рдЧ рд╣реЛрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╕реНрдЯрдмреНрд╕ рдХреА рддрд░рд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред
рдЬрдм рдПрдХ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдореЛрдХ рдпрд╛ рд╕реНрдЯрдм рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рджреВрд╕рд░реА рдУрд░, рдЬрд╛рд╕реВрд╕ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдореБрдЦреНрдп рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЬрд╛рд╕реВрд╕ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЬрд╛рд╕реВрд╕ рдЖрдкрдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ рдХрд┐ рдЬрд╛рд╕реВрд╕ рдФрд░ рдЪреЗрдХ рд╡рд┐рдзрд┐ рдХреЙрд▓, рдореЛрдХ рдФрд░ рд╕реНрдЯрдмреНрд╕ рдХреА рддрд░рд╣ рдХреНрдпрд╛ рдХрд░рддреЗ рд╣реИрдВред (рдЗрд╕рд▓рд┐рдП рд╕реНрдкрд╛рдИ рдирд╛рдо)ред
рдЖрдЗрдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд FooController
рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ, рдЬреЛ FooService
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдПрдХ рдЬрд╛рд╕реВрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддрд╛ рд╣реИред
FooController.groovy
package com.mycompany.myapp import groovy.transform.CompileStatic @CompileStatic class FooController { FooService fooService def doSomething() { render fooService.doSomething("Sally") } }
FooService.groovy
package com.mycompany.myapp import groovy.transform.CompileStatic @CompileStatic class FooService { String doSomething(String name) { "Hi ${name}, FooService did something" } }
рдЯреЗрд╕реНрдЯ рдХреЛрдб:
SpySpec.groovy
package com.mycompany.myapp import grails.testing.web.controllers.ControllerUnitTest import spock.lang.Specification class SpySpec extends Specification implements ControllerUnitTest<FooController> { void "Spy FooService"() { given: " -" def fooService = Spy(FooService) and: " " controller.fooService = fooService when: " " controller.doSomething() then: " " 1 * fooService.doSomething("Sally") >> "A Spy can modify implementation" and: ' ' response.text == "A Spy can modify implementation" } }
рдЬрд╛рд╕реВрд╕реА рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ:
def fooService = Spy(FooService)
рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдореЗрдВ, рдЬрд╛рд╕реВрд╕ рд╣рдореЗрдВ FooService.doSomething(name)
, рдХреЙрд▓ рдХреА рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдкреИрд░рд╛рдореАрдЯрд░ рдорд╛рдиреЛрдВ рдХреА рдХреЙрд▓ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрд╛рд╕реВрд╕ рдПрдХ рдЕрд▓рдЧ рдореВрд▓реНрдп рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдмрджрд▓рддрд╛ рд╣реИред
1 * fooService.doSomething("Sally") >> "A Spy can modify implementation"
рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб 4 рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ:
FooService
рд▓рд┐рдП рдПрдХ рдЬрд╛рд╕реВрд╕ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддрд╛ рд╣реИ- рдирд┐рд░реНрднрд░рддрд╛ рдмрд╛рддрдЪреАрдд рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ
- рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреЗ рдХреБрдЫ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЖрд╡реЗрджрди рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдХреА рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реИ
- рдПрдХ рд╕реНрдЯрдм рдХреЗ рд╕рд╛рде рдирд┐рд░реНрднрд░рддрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЬрдЧрд╣, рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдХреЛ рдЕрд▓рдЧ рдХрд░рддрд╛ рд╣реИ
рдкреВрдЫреЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рд╢реНрди
рдХрд┐рд╕ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ: рдореЙрдХ, рд╕реНрдЯрдм рдпрд╛ рд╕реНрдкрд╛рдИ?
рдпрд╣ рдПрдХ рд╕рд╡рд╛рд▓ рд╣реИ рдЬреЛ рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ рдХрд┐ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдХреМрди рд╕рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИ рддреЛ рдпрд╣ FAQ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ
рдкреНрд░рд╢реНрди: рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдФрд░ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдмреАрдЪ рдЕрдиреБрдмрдВрдз рдХреЗ рд╕рддреНрдпрд╛рдкрди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рд╣реИ?
рдПрдХ: рдпрджрд┐ рдЖрдкрдиреЗ рдЙрддреНрддрд░ рджрд┐рдпрд╛ рд╣рд╛рдВ, рдореЙрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдкреНрд░рд╢реНрди: рдХреНрдпрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рддреЗ рд╕рдордп рдкрд░реАрдХреНрд╖рдг рдХреЗ рддрд╣рдд рдХреЛрдб рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ?
рдПрдХ: рдпрджрд┐ рдЖрдкрдиреЗ рдЙрддреНрддрд░ рджрд┐рдпрд╛ рд╣рд╛рдВ, рд╕реНрдЯрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдкреНрд░рд╢реНрди: рдкрд░реАрдХреНрд╖рдг рдХреЗ рддрд╣рдд рдХреЛрдб рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдЗрдирдкреБрдЯ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ?
рдПрдХ: рдпрджрд┐ рдЖрдкрдиреЗ рдЙрддреНрддрд░ рджрд┐рдпрд╛ рд╣рд╛рдВ, рд╕реНрдЯрдм рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рдкреНрд░рд╢реНрди: рдХреНрдпрд╛ рдЖрдк рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рдФрд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХреЛрдИ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рдмрдЪрд╛ рд╣реИ?
рдПрдХ: рдЬрд╛рд╕реВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЛ
рдХреЛрдб рдЙрджрд╛рд╣рд░рдг
рдЖрдк рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╕рднреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ:
https://github.com/ddelponte/mock-stub-spy
рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ