1 / 65
Spock Framework
Code Factory presentation, Jul, 2018
Stavila Leonid
2 / 65
Introduction
Many modern programming languages are
popular due to the libraries and frameworks that
are written on them. Where would Ruby be
without Rails?
3 / 65
The Java visiting card is primarily
Spring and Hibernate
4 / 65
Scala glorified the Akka framework
5 / 65
Groovy is primarily Gradle and Spock
6 / 65
Kotlin... To be honest, it seems to me that the
ratings of this language are artificially
overstated.
7 / 65
So, Spock
To begin with, this test framework is written in
Groovy.
For large projects, this language is not
recommended, like and Scala, but for small
scripts and tests it is very suitable.
8 / 65
Groovy
In fact, this language is a superset of Java, that
is, if you don’t know how to write-write in Java.
But knowledge of Groovy syntax can save you
time.
Groovy is a kind of script version of Java. It's
simpler, more compact, but at the same time
provides all the power of the JVM.
9 / 65
A classic example is
`hello world`
Java:
System.out.println("Hello world!");
Groovy:
println 'Hello world!'
10 / 65
Economy
println 'Hello world!'

The length of the method name

Two brackets

Quotes. Single quotes are easier to type

Semicolon
11 / 65
Reading data from a file:
BufferedReader br = new BufferedReader(new
FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
System.out.println("line = " + line);
}
} finally {
if (br != null) {
br.close();
}
}
12 / 65
This hulk can be placed
in one line
new File("file.txt")
.eachLine { println "line = $it" }
But most of all I like Groovy's ability to laconically
process collections.
Even revolutionary innovations in Java 8 do not
approach them.
13 / 65
Working with a collection

Java:
List<Integer> results =
Stream.of(1, 2, 3)
.map(v -> v * 2)
.collect(Collectors.toList());

Groovy:
List results = [1, 2, 3]
.collect { it * 2 }
14 / 65
Example of filtering

Java:
List<Integer> evenNumbers =
Stream.of(1, 2, 3, 4).filter(v -> v %
2 == 0).collect(Collectors.toList());

Groovy:
List evenNumbers = [1, 2, 3, 4]
.findAll { it % 2 == 0 }
15 / 65
Let's get back to testing
In the world of Java, JUnit rules in conjunction
with any of the available frameworks for
mocking (Mockito, EasyMock, PowerMock,
etc.).
This is enough to write a test of any complexity,
but this classic approach has drawbacks.
16 / 65

There is no way to give tests a normal and
understandable names. The names of
methods in the style of Camel Case are not
considered, and Junit 5 has not yet received
the proper distribution.
‘shouldAddToCartIfItemIsAvailaibleAndThe
LimitIsNotExceededAnd…..’.
17 / 65

Tests are overloaded with verbose constructs,
such as Collections.singletonList(),
Verify(…), any(MyAwesomeAbstract-
FactoryBaseClass.class) and so on.
18 / 65

Because these frameworks don’t allow a
normal way of dividing the testing process into
a configuration phase, testing itself and
checking the result, very often the tests look
just like a pile of incomprehensible, and
bizarrely mixed code.
19 / 65

In order to test incoming arguments, you need
to build cumbersome structures.
20 / 65

There is no normal support for parameterized
tests. As a result, to cover all cases, we need
to write many similar tests.
21 / 65
When the tests begin to bring a lot of pain, we
try not to use them, or we write trashy, and as a
result we then face even greater pain.
Bad tests don’t guarantee that any new code
change will not break anything else.
22 / 65
Tests written on Groovy look smoother, they are
easier to read and understand. But some
people did not think it was enough, and after a
while a group of enthusiasts wrote their test
framework, Spock.
23 / 65
Spock Framework
For many years, programmers have come to the
conclusion that the more code resembles the
usual sentences of the human language, the
easier and faster it can be understood.
24 / 65
In programming practice, this is not always
applicable. But in testing, due to the fact that all
tests are similar in their idea, this practice is
successfully used.
Programming languages that allow you to flexibly
change your syntax, were able to realize this idea
to the fullest extent.
25 / 65
Currently, tests can be started by customers
who are far from programming. All that is
needed is to write the business requirements in
a compact form. Next, programmers will simply
translate this test into code.
For example: "When the user press the start
button. then the menu is shown as in the
picture".
26 / 65
A simpler example
Addition of numbers 2 and 2 must return 4
This short formulation can already be used as a
test name. It remains only to describe his body.
As in any other test, we have the initial data,
the operation that we need to test and check
the result.
27 / 65
This can be described in three words:
given, when, then:
Addition of numbers 2 and 2 must return 4

given: 2, 2

when: 2 + 2

then: 4
This approach is called BDD (Behavior Driven
Development).
28 / 65
Spock is a modern framework for testing. It's
written in Groovy, includes tools for stubbing
and mocking and embodies the idea of BDD. In
fact, this is a domain specific language (DSL),
created specifically for writing tests.
It is an extension of the Junit runner and you do
not have to change anything in the
infrastructure to run these tests.
29 / 65
Advantages

Groovy is not as verbose as Java

The special syntax is aimed specifically at testing

Built-in support for Stubs and Mocks

Extends Junit runner

Simple testing with parameters

Keywords for all testing phases (given, when, then …)

Ease of describing methods

Many other specific features
30 / 65
Basics
31 / 65
Specification Template
class MyFirstSpecification extends Specification {
// fields
// fixture methods
// feature methods
// helper methods
}
32 / 65
Fixture Methods
Run before every feature method:
def setup() {}
Run after every feature method:
def cleanup() {}
Run before the first feature method:
def setupSpec() {}
Run after the last feature method:
33 / 65
Blocks Order

given: data initialization goes here (includes
creating mocks)

when: invoke your test subject here and assign it
to a variable

then: assert data here

cleanup: optional

where: optional: provide parameterized data
(tables or pipes)
34 / 65
Or

given

expect: combines when with then

cleanup

where
35 / 65
Junit comparison
Spock JUnit
Specification Test class
setup() @Before
cleanup() @After
setupSpec() @BeforeClass
cleanupSpec() @AfterClass
Feature Test
Feature method Test method
Data-driven feature Theory
Condition Assertion
Exception condition @Test(expected=…)​
Interaction Mock expectation (e.g. in Mockito)
36 / 65
Data Driven Testing
37 / 65
Data Tables
class Math extends Specification {
def "maximum of two numbers"(int a, int
b, int c) {
expect:
Math.max(a, b) == c
where:
a | b || c
1 | 3 || 3 // passes
7 | 4 || 4 // fails
0 | 0 || 0 // passes
38 / 65
Unrolling
A method annotated with @Unroll will have its
rows from data table reported independently:
@Unroll
def "maximum of two numbers"() { ... }
39 / 65
Result with Unroll
maximum of two numbers[0] PASSED
maximum of two numbers[1] FAILED
Math.max(a, b) == c
| | | | |
| 7 0 | 7
42 false
40 / 65
Result Without Unroll
We have to figure out which row failed manually
maximum of two numbers FAILED
Condition not satisfied:
Math.max(a, b) == c
| | | | |
| 7 0 | 7
42 false
41 / 65
Data Pipes
Right side must be Collection, String or Iterable.
where:
a << [3, 7, 0]
b << [5, 0, 0]
c << [5, 7, 0]
42 / 65
Multi-Variable Data Pipes
where:
[a,b,c] << sql.rows("select a,b,c from maxdata")
where:
row << sql.rows("select * from maxdata")
// pick apart columns
a = row.a
b = row.b
c = row.c
43 / 65
Ignore some variable
where:
[a,b] << [[1,2,3],[1,2,3],[4,5,6]]
[a, b, _, c] << sql.rows("select * from maxdata")
44 / 65
Combine data tables, pipes and
assignments
where:
a | _
3 | _
7 | _
0 | _
b << [5, 0, 0]
c = a > b ? a : b
45 / 65
Unrolled method names
parameters
Property Access:
def "#person is #person.age years old"() {...}
Zero-argument method call:
def "#person.name.toUpperCase()"() { ... }
46 / 65
Interaction Based Testing
47 / 65
Mocking
48 / 65
Create Mock
Mocks are Lenient (return default value for undefined mock
calls)
Subscriber subscriber = Mock()
def subscriber2 = Mock(Subscriber)
49 / 65
Using Mock
def "should send messages to all subscribers"() {
when:
publisher.send("hello")
then:
1 * subscriber.receive("hello") //subsriber should call
receive with "hello" once.
1 * subscriber2.receive("hello")
}
50 / 65
Cardinality
1 * subscriber.receive("hello") // exactly one call
0 * subscriber.receive("hello") // zero calls
(1..3) * subscriber.receive("hello") // between one and three
calls (inclusive)
(1.._) * subscriber.receive("hello") // at least one call
(_..3) * subscriber.receive("hello") // at most three calls
_ * subscriber.receive("hello") // any number of calls,
including zero
51 / 65
Constraints
52 / 65
Target
A call to `subscriber`:
1 * subscriber.receive("hello")
A call to any mock object:
1 * _.receive("hello")
53 / 65
Method
A method named 'receive'
1 * subscriber.receive("hello")
A method whose name matches the given regular
expression. Here: method name starts with 'r' and
ends with 'e'.
1 * subscriber./r.*e/("hello")
54 / 65
Argument
1 * subscriber.receive("hello") // an argument that is
equal to the String "hello"
1 * subscriber.receive(!"hello") // an argument that is
unequal to the String "hello"
1 * subscriber.receive() // the empty argument list
(would never match in our example)
1 * subscriber.receive(_) // any single argument
(including null)
1 * subscriber.receive(*_) // any argument list
(including the empty argument list)
55 / 65
Argument
1 * subscriber.receive(!null) // any non-null argument
1 * subscriber.receive(_ as String) // any non-null argument
that is-a String
1 * subscriber.receive({ it.size() > 3 }) // an argument that
satisfies the given predicate
// (here: message length is greater than 3)
56 / 65
Specify mock calls at creation
class MySpec extends Specification {
Subscriber subscriber = Mock {
1 * receive("hello")
1 * receive("goodbye")
}
}
57 / 65
Group interactions
with(mock) {
1 * receive("hello")
1 * receive("goodbye")
}
58 / 65
Stubbing
Stubs don’t have cardinality (matches invocation
anyTimes)
def subscriber = Stub(Subscriber)
...
subscriber.receive(_) >> "ok"
Whenever the subscriber receives a message, make
it respond with ‘ok’.
59 / 65
Returning different values on
sucessive calls
subscriber.receive(_) >>> ["ok", "error", "error", "ok"]
subscriber.receive(_) >>> ["ok", "fail", "ok"] >> { throw
new InternalError() } >> "ok"
60 / 65
Extensions
@Ignore(reason = "TODO")
@IgnoreRest
@IgnoreIf({ spock.util.environment.Jvm.isJava5()) })
@Requires({ os.windows })
@Timeout(5)
@Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
@Title("This tests if..."
@Narrative("some detailed explanation")
@Issue("http://redmine/23432")
@Subject
61 / 65
Disadvantages of Spock
Due to some differences between Java and Groovy, for
example, different numeric data types, some tests on Groovy
look more cumbersome because type casting is required.
Also Spock is not good friends with the Spring Framework.
Here is an example of how you can use objects from the
Spring context:
62 / 65
Spring Boot
The recommended way to use Spock mocks in
@WebMvcTest tests, is to use an embedded config
annotated with @TestConfiguration and to create the
mocks using the DetachedMockFactory.
63 / 65
@WebMvcTest
class WebMvcTestIntegrationSpec extends Specification {
@Autowired
MockMvc mvc
@Autowired
HelloWorldService helloWorldService
def "spring context loads for web mvc slice"() {
given:
helloWorldService.getHelloMessage() >> 'hello world'
expect: "controller is available"
mvc.perform(MockMvcRequestBuilders.get("/"))
.andExpect(status().isOk())
.andExpect(content().string("hello world"))
}
@TestConfiguration
static class MockConfig {
def detachedMockFactory = new DetachedMockFactory();
@Bean
HelloWorldService helloWorldService() {
return detachedMockFactory.Stub(HelloWorldService)
}
}
}
64 / 65
Sources

http://wittyginger.com/post/groovy-is-still-better-than-java/

http://jakubdziworski.github.io/java/groovy/spock/2016/05/14/spock-chea

http://spockframework.org/spock/docs/1.1-rc-3/module_spring.html
65 / 65
Thanks ;)

Spock Framework

  • 1.
    1 / 65 SpockFramework Code Factory presentation, Jul, 2018 Stavila Leonid
  • 2.
    2 / 65 Introduction Manymodern programming languages are popular due to the libraries and frameworks that are written on them. Where would Ruby be without Rails?
  • 3.
    3 / 65 TheJava visiting card is primarily Spring and Hibernate
  • 4.
    4 / 65 Scalaglorified the Akka framework
  • 5.
    5 / 65 Groovyis primarily Gradle and Spock
  • 6.
    6 / 65 Kotlin...To be honest, it seems to me that the ratings of this language are artificially overstated.
  • 7.
    7 / 65 So,Spock To begin with, this test framework is written in Groovy. For large projects, this language is not recommended, like and Scala, but for small scripts and tests it is very suitable.
  • 8.
    8 / 65 Groovy Infact, this language is a superset of Java, that is, if you don’t know how to write-write in Java. But knowledge of Groovy syntax can save you time. Groovy is a kind of script version of Java. It's simpler, more compact, but at the same time provides all the power of the JVM.
  • 9.
    9 / 65 Aclassic example is `hello world` Java: System.out.println("Hello world!"); Groovy: println 'Hello world!'
  • 10.
    10 / 65 Economy println'Hello world!'  The length of the method name  Two brackets  Quotes. Single quotes are easier to type  Semicolon
  • 11.
    11 / 65 Readingdata from a file: BufferedReader br = new BufferedReader(new FileReader("file.txt")); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); System.out.println("line = " + line); } } finally { if (br != null) { br.close(); } }
  • 12.
    12 / 65 Thishulk can be placed in one line new File("file.txt") .eachLine { println "line = $it" } But most of all I like Groovy's ability to laconically process collections. Even revolutionary innovations in Java 8 do not approach them.
  • 13.
    13 / 65 Workingwith a collection  Java: List<Integer> results = Stream.of(1, 2, 3) .map(v -> v * 2) .collect(Collectors.toList());  Groovy: List results = [1, 2, 3] .collect { it * 2 }
  • 14.
    14 / 65 Exampleof filtering  Java: List<Integer> evenNumbers = Stream.of(1, 2, 3, 4).filter(v -> v % 2 == 0).collect(Collectors.toList());  Groovy: List evenNumbers = [1, 2, 3, 4] .findAll { it % 2 == 0 }
  • 15.
    15 / 65 Let'sget back to testing In the world of Java, JUnit rules in conjunction with any of the available frameworks for mocking (Mockito, EasyMock, PowerMock, etc.). This is enough to write a test of any complexity, but this classic approach has drawbacks.
  • 16.
    16 / 65  Thereis no way to give tests a normal and understandable names. The names of methods in the style of Camel Case are not considered, and Junit 5 has not yet received the proper distribution. ‘shouldAddToCartIfItemIsAvailaibleAndThe LimitIsNotExceededAnd…..’.
  • 17.
    17 / 65  Testsare overloaded with verbose constructs, such as Collections.singletonList(), Verify(…), any(MyAwesomeAbstract- FactoryBaseClass.class) and so on.
  • 18.
    18 / 65  Becausethese frameworks don’t allow a normal way of dividing the testing process into a configuration phase, testing itself and checking the result, very often the tests look just like a pile of incomprehensible, and bizarrely mixed code.
  • 19.
    19 / 65  Inorder to test incoming arguments, you need to build cumbersome structures.
  • 20.
    20 / 65  Thereis no normal support for parameterized tests. As a result, to cover all cases, we need to write many similar tests.
  • 21.
    21 / 65 Whenthe tests begin to bring a lot of pain, we try not to use them, or we write trashy, and as a result we then face even greater pain. Bad tests don’t guarantee that any new code change will not break anything else.
  • 22.
    22 / 65 Testswritten on Groovy look smoother, they are easier to read and understand. But some people did not think it was enough, and after a while a group of enthusiasts wrote their test framework, Spock.
  • 23.
    23 / 65 SpockFramework For many years, programmers have come to the conclusion that the more code resembles the usual sentences of the human language, the easier and faster it can be understood.
  • 24.
    24 / 65 Inprogramming practice, this is not always applicable. But in testing, due to the fact that all tests are similar in their idea, this practice is successfully used. Programming languages that allow you to flexibly change your syntax, were able to realize this idea to the fullest extent.
  • 25.
    25 / 65 Currently,tests can be started by customers who are far from programming. All that is needed is to write the business requirements in a compact form. Next, programmers will simply translate this test into code. For example: "When the user press the start button. then the menu is shown as in the picture".
  • 26.
    26 / 65 Asimpler example Addition of numbers 2 and 2 must return 4 This short formulation can already be used as a test name. It remains only to describe his body. As in any other test, we have the initial data, the operation that we need to test and check the result.
  • 27.
    27 / 65 Thiscan be described in three words: given, when, then: Addition of numbers 2 and 2 must return 4  given: 2, 2  when: 2 + 2  then: 4 This approach is called BDD (Behavior Driven Development).
  • 28.
    28 / 65 Spockis a modern framework for testing. It's written in Groovy, includes tools for stubbing and mocking and embodies the idea of BDD. In fact, this is a domain specific language (DSL), created specifically for writing tests. It is an extension of the Junit runner and you do not have to change anything in the infrastructure to run these tests.
  • 29.
    29 / 65 Advantages  Groovyis not as verbose as Java  The special syntax is aimed specifically at testing  Built-in support for Stubs and Mocks  Extends Junit runner  Simple testing with parameters  Keywords for all testing phases (given, when, then …)  Ease of describing methods  Many other specific features
  • 30.
  • 31.
    31 / 65 SpecificationTemplate class MyFirstSpecification extends Specification { // fields // fixture methods // feature methods // helper methods }
  • 32.
    32 / 65 FixtureMethods Run before every feature method: def setup() {} Run after every feature method: def cleanup() {} Run before the first feature method: def setupSpec() {} Run after the last feature method:
  • 33.
    33 / 65 BlocksOrder  given: data initialization goes here (includes creating mocks)  when: invoke your test subject here and assign it to a variable  then: assert data here  cleanup: optional  where: optional: provide parameterized data (tables or pipes)
  • 34.
    34 / 65 Or  given  expect:combines when with then  cleanup  where
  • 35.
    35 / 65 Junitcomparison Spock JUnit Specification Test class setup() @Before cleanup() @After setupSpec() @BeforeClass cleanupSpec() @AfterClass Feature Test Feature method Test method Data-driven feature Theory Condition Assertion Exception condition @Test(expected=…)​ Interaction Mock expectation (e.g. in Mockito)
  • 36.
    36 / 65 DataDriven Testing
  • 37.
    37 / 65 DataTables class Math extends Specification { def "maximum of two numbers"(int a, int b, int c) { expect: Math.max(a, b) == c where: a | b || c 1 | 3 || 3 // passes 7 | 4 || 4 // fails 0 | 0 || 0 // passes
  • 38.
    38 / 65 Unrolling Amethod annotated with @Unroll will have its rows from data table reported independently: @Unroll def "maximum of two numbers"() { ... }
  • 39.
    39 / 65 Resultwith Unroll maximum of two numbers[0] PASSED maximum of two numbers[1] FAILED Math.max(a, b) == c | | | | | | 7 0 | 7 42 false
  • 40.
    40 / 65 ResultWithout Unroll We have to figure out which row failed manually maximum of two numbers FAILED Condition not satisfied: Math.max(a, b) == c | | | | | | 7 0 | 7 42 false
  • 41.
    41 / 65 DataPipes Right side must be Collection, String or Iterable. where: a << [3, 7, 0] b << [5, 0, 0] c << [5, 7, 0]
  • 42.
    42 / 65 Multi-VariableData Pipes where: [a,b,c] << sql.rows("select a,b,c from maxdata") where: row << sql.rows("select * from maxdata") // pick apart columns a = row.a b = row.b c = row.c
  • 43.
    43 / 65 Ignoresome variable where: [a,b] << [[1,2,3],[1,2,3],[4,5,6]] [a, b, _, c] << sql.rows("select * from maxdata")
  • 44.
    44 / 65 Combinedata tables, pipes and assignments where: a | _ 3 | _ 7 | _ 0 | _ b << [5, 0, 0] c = a > b ? a : b
  • 45.
    45 / 65 Unrolledmethod names parameters Property Access: def "#person is #person.age years old"() {...} Zero-argument method call: def "#person.name.toUpperCase()"() { ... }
  • 46.
    46 / 65 InteractionBased Testing
  • 47.
  • 48.
    48 / 65 CreateMock Mocks are Lenient (return default value for undefined mock calls) Subscriber subscriber = Mock() def subscriber2 = Mock(Subscriber)
  • 49.
    49 / 65 UsingMock def "should send messages to all subscribers"() { when: publisher.send("hello") then: 1 * subscriber.receive("hello") //subsriber should call receive with "hello" once. 1 * subscriber2.receive("hello") }
  • 50.
    50 / 65 Cardinality 1* subscriber.receive("hello") // exactly one call 0 * subscriber.receive("hello") // zero calls (1..3) * subscriber.receive("hello") // between one and three calls (inclusive) (1.._) * subscriber.receive("hello") // at least one call (_..3) * subscriber.receive("hello") // at most three calls _ * subscriber.receive("hello") // any number of calls, including zero
  • 51.
  • 52.
    52 / 65 Target Acall to `subscriber`: 1 * subscriber.receive("hello") A call to any mock object: 1 * _.receive("hello")
  • 53.
    53 / 65 Method Amethod named 'receive' 1 * subscriber.receive("hello") A method whose name matches the given regular expression. Here: method name starts with 'r' and ends with 'e'. 1 * subscriber./r.*e/("hello")
  • 54.
    54 / 65 Argument 1* subscriber.receive("hello") // an argument that is equal to the String "hello" 1 * subscriber.receive(!"hello") // an argument that is unequal to the String "hello" 1 * subscriber.receive() // the empty argument list (would never match in our example) 1 * subscriber.receive(_) // any single argument (including null) 1 * subscriber.receive(*_) // any argument list (including the empty argument list)
  • 55.
    55 / 65 Argument 1* subscriber.receive(!null) // any non-null argument 1 * subscriber.receive(_ as String) // any non-null argument that is-a String 1 * subscriber.receive({ it.size() > 3 }) // an argument that satisfies the given predicate // (here: message length is greater than 3)
  • 56.
    56 / 65 Specifymock calls at creation class MySpec extends Specification { Subscriber subscriber = Mock { 1 * receive("hello") 1 * receive("goodbye") } }
  • 57.
    57 / 65 Groupinteractions with(mock) { 1 * receive("hello") 1 * receive("goodbye") }
  • 58.
    58 / 65 Stubbing Stubsdon’t have cardinality (matches invocation anyTimes) def subscriber = Stub(Subscriber) ... subscriber.receive(_) >> "ok" Whenever the subscriber receives a message, make it respond with ‘ok’.
  • 59.
    59 / 65 Returningdifferent values on sucessive calls subscriber.receive(_) >>> ["ok", "error", "error", "ok"] subscriber.receive(_) >>> ["ok", "fail", "ok"] >> { throw new InternalError() } >> "ok"
  • 60.
    60 / 65 Extensions @Ignore(reason= "TODO") @IgnoreRest @IgnoreIf({ spock.util.environment.Jvm.isJava5()) }) @Requires({ os.windows }) @Timeout(5) @Timeout(value = 100, unit = TimeUnit.MILLISECONDS) @Title("This tests if..." @Narrative("some detailed explanation") @Issue("http://redmine/23432") @Subject
  • 61.
    61 / 65 Disadvantagesof Spock Due to some differences between Java and Groovy, for example, different numeric data types, some tests on Groovy look more cumbersome because type casting is required. Also Spock is not good friends with the Spring Framework. Here is an example of how you can use objects from the Spring context:
  • 62.
    62 / 65 SpringBoot The recommended way to use Spock mocks in @WebMvcTest tests, is to use an embedded config annotated with @TestConfiguration and to create the mocks using the DetachedMockFactory.
  • 63.
    63 / 65 @WebMvcTest classWebMvcTestIntegrationSpec extends Specification { @Autowired MockMvc mvc @Autowired HelloWorldService helloWorldService def "spring context loads for web mvc slice"() { given: helloWorldService.getHelloMessage() >> 'hello world' expect: "controller is available" mvc.perform(MockMvcRequestBuilders.get("/")) .andExpect(status().isOk()) .andExpect(content().string("hello world")) } @TestConfiguration static class MockConfig { def detachedMockFactory = new DetachedMockFactory(); @Bean HelloWorldService helloWorldService() { return detachedMockFactory.Stub(HelloWorldService) } } }
  • 64.
  • 65.