© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Unless otherwise indicated, these slides are © 2012-2014 Sam Brannen and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
Testing with Spring 4.x
Sam Brannen
@sam_brannen
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Sam Brannen
•  Spring and Java Consultant @ Swiftmind
•  Java Developer for over 15 years
•  Spring Framework Core Committer since 2007
•  Component lead for spring-test
•  Spring Trainer
•  Speaker on Spring, Java, and testing
•  Swiss Spring User Group Lead
2
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Areas of expertise
–  Spring *
–  Java EE
–  Software Architecture
–  Software Engineering Best
Practices
Where you find us
•  Zurich, Switzerland
•  @swiftmind
•  http://www.swiftmind.com
3
Your experts for Spring and Enterprise Java
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
A show of hands…
4
?
?
?
?
?
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Agenda
•  Deprecations, Pruning, & Dependencies
•  Recap of Testing with Spring 3.x
•  Testing Themes in 4.x
•  Details, Tips, & Examples
•  Q&A
5
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Deprecations, Pruning, & Dependencies
6
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Spring Cleaning in 4.x
•  All deprecated packages removed
•  Many deprecated methods and fields removed as well
•  Mind the deprecation warnings… before upgrading from 3.x
7
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Pruning in 4.0
•  JUnit 3.8 support
•  Use JUnit 4 or TestNG
•  @ExpectedException
•  Use @Test(expected) or @Rule ExpectedException in JUnit
•  Use @Test(expectedExceptions) in TestNG
•  @NotTransactional
•  Use @Transactional(propagation=NOT_SUPPORTED)
•  SimpleJdbcTestUtils
•  Use JdbcTestUtils, ScriptUtils, or @Sql
8
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Dependency Upgrades in 4.0
•  Servlet API mocks
•  Now based on Servlet 3.0
•  Servlet 2.5 still supported in production
•  JUnit
•  Tested against à 4.11
•  TestNG
•  Tested against à 6.8.5
9
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Dependency Upgrades in 4.1
•  JUnit
•  Minimum version à 4.9
•  Recommended à 4.11
•  TestNG
•  Tested against à 6.8.8
10
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Testing with Spring 3.x
11
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Testing Themes from Spring 3.x (1/2)
•  Embedded databases
•  <jdbc:embedded-database /> & <jdbc:initialize-database />
•  EmbeddedDatabaseBuilder & EmbeddedDatabaseFactoryBean
•  @Configuration classes
•  @ActiveProfiles
•  ApplicationContextInitializers
12
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Testing Themes from Spring 3.x (2/2)
•  @WebAppConfiguration
•  Loading WebApplicationContexts
•  Testing request- and session-scoped beans
•  @ContextHierarchy
•  Web, Batch, etc.
•  Spring MVC Test framework
•  Server-side MVC and REST tests
•  Client-side REST tests
13
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Web Integration Test (1/2)
14
@RunWith(SpringJUnit4ClassRunner.class)	
@WebAppConfiguration	
@ContextHierarchy({	
	@ContextConfiguration(classes = RootConfig.class),	
	@ContextConfiguration(classes = WebConfig.class)	
})	
@ActiveProfiles("dev")	
public class ControllerIntegrationTests {	
@Autowired	
private WebApplicationContext wac;	
private MockMvc mockMvc;	
// ...
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Web Integration Test (2/2)
15
@Before	
public void setup() {	
this.mockMvc = MockMvcBuilders	
.webAppContextSetup(this.wac).build();	
}	
	
@Test	
public void person() throws Exception {	
this.mockMvc.perform(get("/person/42")	
.accept(MediaType.APPLICATION_JSON))	
.andExpect(status().isOk())	
.andExpect(content().string("{"name":"Sam"}"));	
}
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Testing Themes in Spring 4.0
16
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.0 (1/3)
•  SocketUtils
•  Scan for available UDP & TCP ports
•  ActiveProfilesResolver API
•  Programmatic alternative to static profile strings
•  Set via new resolver attribute in @ActiveProfiles
•  Meta-annotation support for tests
•  Attribute overrides (optional and required)
17
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.0 (2/3)
•  New deleteFromTableWhere() method in
AbstractTransactional*SpringContextTests
•  * à JUnit4 or TestNG
•  New verify() and reset() methods in
AnnotationDrivenStaticEntityMockingControl
•  Multi-line SQL comments:
•  ResourceDatabasePopulator, JdbcTestUtils, ScriptUtils
18
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.0 (3/3)
•  TestContext converted to an interface
•  Allows TestContext to be mocked in unit tests
•  Simultaneous use of classes and locations in
@ContextConfiguration for hybrid loaders
•  See Spring Boot
•  Servlet API mock improvements
19
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Testing Themes in Spring 4.1
20
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.1 – Context Config
•  Context config with Groovy scripts
•  Declarative configuration for test property sources
•  @TestPropertySource
21
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.1 – Transactions and SQL
•  Programmatic test transaction management
•  TestTransaction API
•  Declarative SQL script execution
•  @Sql, @SqlConfig, @SqlGroup
•  Improved docs for transactional tests
22
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.1 – Bootstrap & TestExecutionListeners
•  TestContext bootstrap strategy
•  TestContextBootstrapper & @BootstrapWith
•  Automatic discovery of default TestExecutionListeners
•  Uses SpringFactoriesLoader
•  Already used by Spring Security
•  Merging custom TestExecutionListeners with defaults
•  @TestExecutionListeners(mergeMode=MERGE_WITH_DEFAULTS)
•  Defaults to REPLACE_DEFAULTS
23
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.1 – Spring MVC Test
•  Assert JSON responses with JSON Assert
•  Complements JSONPath support
•  Create MockMvcBuilder recipes with MockMvcConfigurer
•  Developed to apply Spring Security setup but can be used by anyone
•  AsyncRestTemplate support in MockRestServiceServer
•  For asynchronous client-side testing
24
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
New in 4.1 – Odds & Ends
•  AssertThrows: refactored to support Throwable
•  Various improvements to Servlet API mocks
25
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Details, Tips, & Examples
26
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
SocketUtils
•  Utility class introduced in Spring Framework 4.0
•  Located in spring-core
•  Can be used in production code
•  But ideal for embedded testing scenarios (SMTP, FTP, etc.)
•  Finds available TCP and UDP ports on localhost
•  Default port range: 1024 à 65535
•  See Javadoc for all options
•  Straightforward usage in Java and @Configuration classes
27
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Using SocketUtils in XML Config
•  Via fully qualified class name and SpEL
	
<bean id="bean1" ... p:port=	
"#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" />	
•  Via socketUtils bean and SpEL (as of Spring 4.0.8 & 4.1.1)
<bean id="socketUtils" 	
class="org.springframework.util.SocketUtils" />	
<bean id="bean1" ... 	
p:port="#{socketUtils.findAvailableTcpPort(12000)}" />	
<bean id="bean2" ... 	
p:port="#{socketUtils.findAvailableTcpPort(30000)}" />
28
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Tip: Define Free Port as Bean
•  Define the free port as a Spring Bean…
	
<bean id="serverPort" class="java.lang.Integer" 	
c:_="#{T(socketUtils.findAvailableTcpPort()}" />	
	
•  Then reference the serverPort from other beans
•  Or inject it into components, @Configuration classes, and tests
29
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: @ActiveProfiles – Declarative
30
@RunWith(SpringJUnit4ClassRunner.class)	
@ContextConfiguration	
@ActiveProfiles("dev")	
public class IntegrationTests {	
// ...	
}	
But what if static
isn’t good enough?
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: @ActiveProfiles – Programmatic
31
public class MyResolver implements ActiveProfilesResolver {	
public String[] resolve(Class<?> testClass) {	
// resolve bean definition profiles for test class	
}	
}	
	
@RunWith(SpringJUnit4ClassRunner.class)	
@ContextConfiguration	
@ActiveProfiles(resolver = MyProfileResolver.class)	
public class IntegrationTests {	
// ...	
}	
Implement custom resolver
And declare it
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Composable Stereotypes – Quick Review
•  Combining meta-annotations on a custom stereotype
•  Automatically detected: no configuration necessary!
32
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Duplicate Test Configuration == Bad
@ContextConfiguration("/test-config.xml")	
@ActiveProfiles("dev")	
@Transactional	
public class OrderRepositoryTests {	
}	
	
@ContextConfiguration("/test-config.xml")	
@ActiveProfiles("dev")	
@Transactional	
public class UserRepositoryTests {	
}
33
duplication
duplication
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Custom Test Annotation == Good
@Target(TYPE)	
@Retention(RUNTIME)	
@ContextConfiguration("/test-config.xml")	
@ActiveProfiles("dev")	
@Transactional	
public @interface TransactionalDevTest { }	
	
	
@TransactionalDevTest	
public class OrderRepositoryTests { }	
	
@TransactionalDevTest	
public class UserRepositoryTests { }
	
34
common config
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Composable Annotations with Overrides
•  Composable annotations may override attributes of meta-
annotations
•  Purely convention-based
•  Matched by attribute name and type
•  Can lead to potential naming conflicts
•  Cannot override the value attribute
35
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Optional Annotation Attribute Override
@Target(TYPE)	
@Retention(RUNTIME)	
@ContextConfiguration	
@Transactional	
public @interface TransactionalTest {	
	String[] locations() default "/test-config.xml";	
}	
	
	
	
@TransactionalTest(locations = "/order-test-config.xml")	
public class OrderRepositoryTests { }	
36
optional: overrides default
default
locations declared
here will be ignored
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Required Annotation Attribute Override
@Target(TYPE)	
@Retention(RUNTIME)	
@ContextConfiguration	
@Transactional	
public @interface TransactionalTest {	
	String[] locations();	
}	
	
	
	
@TransactionalTest(locations = "/order-test-config.xml")	
public class OrderRepositoryTests { }	
37
required
no default
locations declared
here will be ignored
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Groovy Beans in Spring
•  Spring Framework 4.0 introduced support for the Groovy Bean
Definition DSL via the GroovyBeanDefinitionReader and
GenericGroovyApplicationContext
•  Spring Framework 4.1 introduces support for Groovy scripts in
web applications via the GroovyWebApplicationContext
•  Testing support added in 4.1…
38
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Spring Bean Definitions with Groovy DSL
import org.mypackage.domain.Person;	
beans {	
xmlns util: 'http://www.springframework.org/schema/util'	
person1(Person) {	
name = "homer"	
age = 45	
props = [overweight: true, height: "1.8m"]	
children = ["bart", "lisa"]	
}	
util.list(id: 'foo') {	
value 'one'	
value 'two'	
}	
}	
39
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Groovy Scripts for Context Config in Tests
•  Spring Framework 4.1 introduces support for Groovy scripts in
integration tests via @ContextConfiguration
•  Scripts are configured via the locations or value attribute
o  Resource semantics identical to XML
o  Default detected with “Context.groovy” suffix in same package
•  The inheritLocations flag is fully supported
•  Groovy and XML configuration can be declared together
•  Groovy WebApplicationContexts supported via
@WebAppConfiguration
40
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Groovy Script Config
@RunWith(SpringJUnit4ClassRunner.class)	
@ContextConfiguration("/context.groovy")	
public class GroovyPersonTests {	
	
@Autowired	
private Person person;	
	
/* test methods using person bean */	
}	
41
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Default Groovy Script Detection
public com.example;	
	
@RunWith(SpringJUnit4ClassRunner.class)	
// ApplicationContext will be loaded from	
// “classpath:com/example/MyTestContext.groovy”	
@ContextConfiguration	
public class MyTest {	
/* ... */	
}	
42
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Groovy & XML Config Together
@RunWith(SpringJUnit4ClassRunner.class)	
// ApplicationContext will be loaded from	
// “/context.groovy” and “/context.xml”	
@ContextConfiguration({ "/context.groovy", "/context.xml" })	
public class MyTest {	
/* ... */	
}	
43
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Test Property Sources
•  Spring 3.1 introduced PropertySources abstraction
•  Configured via Environment or via @PropertySource
•  Spring 4.1 supports declarative test property sources
•  Configured via @TestPropertySource
•  Test property sources are declared via annotation attributes
•  locations or value: resource locations
•  properties: inlined properties
•  both are inherited by default
44
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
@TestPropertySource – locations
•  String array of resource locations for Java Properties files
•  Both traditional *.properties and XML formats are supported
•  Resource semantics are identical to those for locations in
@ContextConfiguration
45
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: @TestPropertySource – locations
@ContextConfiguration	
@TestPropertySource("/test.properties")	
public class MyIntegrationTests {	
	// class body...	
}
46
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
@TestPropertySource – properties
•  Inlined properties can be declared as key/value pairs
•  Uses syntax for entries in Java properties files:
•  "key=value"
•  "key:value"
•  "key value"
47
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: @TestPropertySource – properties
@ContextConfiguration	
@TestPropertySource(	
properties = {"foo=bar", "port: 4242"}	
)	
public class MyIntegrationTests {	
	// class body...	
}
48
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Default Properties File Detection
•  If neither locations nor properties are defined, a default properties
file will be detected
•  Default is detected with “.properties” suffix in same package
•  If the class is com.example.MyTest, the default properties file is
“classpath:com/example/MyTest.properties”
•  Exception is thrown if default is not present
49
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
@TestPropertySource – Precedence
50
Inlined
Files
Application & System
test
precedence
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: @TestPropertySource – locations & properties
@ContextConfiguration	
@TestPropertySource(	
locations = "/test.properties",	
properties = "port: 4242"	
)	
public class MyIntegrationTests {	
	// class body...	
}
51
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Programmatic Transaction Management in Tests
•  History Lesson: Spring’s JUnit 3.8 testing framework supported
endTransaction() and startNewTransaction() methods in
AbstractTransactionalSpringContextTests
•  But… the Spring TestContext Framework, introduced in Spring
2.5, did not… until now
•  Due to popular demand, Spring 4.1 introduces a new
TestTransaction API
52
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Transactions in Spring
•  Spring-managed transactions: managed by Spring in the
ApplicationContext
•  @Transactional and AOP
•  Application-managed transactions: managed programmatically within
application code
•  TransactionTemplate and TransactionSynchronizationManager
•  Test-managed transactions: managed by the Spring TestContext
Framework
•  @Transactional on test classes and test methods
•  Transaction is rolled back by default!
53
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Declarative Transaction Management in Tests
@RunWith(SpringJUnit4ClassRunner.class)	
@ContextConfiguration	
@Transactional	
public class TransactionalTests {	
	
@Test	
public void withinTransaction() {	
/* ... */	
}
54
What if we want to
stop & start the
transaction within the
test method?
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
TestTransaction API
•  Static methods for interacting with test-managed transactions
•  isActive()
•  isFlaggedForRollback()
•  flagForCommit()
•  flagForRollback()
•  end()
•  start()
55
query status
change default rollback setting
end: roll back or commit based on flag
start: new tx with default rollback setting
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Programmatic Transaction Management in Tests
@Test	
public void withinTransaction() {	
// assert initial state in test database:	
assertNumUsers(2);	
	
deleteFromTables("user");	
	
// changes to the database will be committed	
TestTransaction.flagForCommit();	
TestTransaction.end();	
assertFalse(TestTransaction.isActive());	
assertNumUsers(0);	
	
TestTransaction.start();	
// perform other actions against the database that will	
// be automatically rolled back after the test completes...	
}
56
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Executing SQL Scripts
57
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Embedded Database in Java Config
58
@Bean	
public DataSource dataSource() {	
return new EmbeddedDatabaseBuilder()	
.setType(H2)	
.setScriptEncoding("UTF-8")	
.ignoreFailedDrops(true)	
.addScript("schema.sql")	
.addScripts("user_data.sql", "country_data.sql")	
.build();	
}	
API greatly improved
in Spring 4.0.3
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Embedded Database in XML Config
<jdbc:embedded-database id="dataSource" type="H2">	
<jdbc:script location="classpath:/schema.sql" />	
<jdbc:script location="classpath:/user_data.sql" />	
</jdbc:embedded-database>	
	
59
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: Populate Database in XML Config
<jdbc:initialize-database data-source="dataSource">	
<jdbc:script location="classpath:/schema_01.sql" />	
<jdbc:script location="classpath:/schema_02.sql" />	
<jdbc:script location="classpath:/data_01.sql" />	
<jdbc:script location="classpath:/data_02.sql" />	
</jdbc:initialize-database>
60
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Executing SQL per Test Method
•  The previous techniques are very useful for setting up the initial
database state
•  Q: But how can we execute SQL scripts per test method?
•  A: Programmatically via ScriptUtils,
ResourceDatabasePopulator, or abstract transactional base test
classes for JUnit and TestNG.
•  Q: OK, but how can we do that declaratively?
•  A: Via @Sql in Spring Framework 4.1!
61
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Executing SQL Scripts Declaratively with @Sql
•  @Sql: declared on a test class or test method
•  method-level overrides class-level
•  The scripts attribute is used to declare resource locations for
SQL scripts
•  semantics analogous to locations in @ContextConfiguration
•  Scripts can be executed before or after a test method
•  configured via the executionPhase attribute of @Sql
62
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Ex: @Sql in Action
@ContextConfiguration	
@Sql({ "schema1.sql", "data1.sql" })	
public class SqlScriptsTests {	
	
@Test	
public void classLevelScripts() { /* ... */ }	
	
@Test	
@Sql({ "schema2.sql", "data2.sql" })	
public void methodLevelScripts() { /* ... */ }	
	
63
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Default SQL Script Detection
•  If no scripts are declared, a default script will be detected
•  Depending on where @Sql is declared
•  Class-level: for com.example.DbTest, the default is “classpath:com/
example/DbTest.sql”
•  Method-level: for com.example.DbTest.test(), the default is
“classpath:com/example/DbTest.test.sql”
•  If the default is not present, an exception is thrown
64
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Declaring Multiple @Sql Sets
•  Declare multiple sets of @Sql scripts for varying configuration
•  Java 8: use @Sql as a repeatable annotation
•  Java 6 & 7: wrap @Sql sets in @SqlGroup
65
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
@Sql as a Repeatable Annotation (Java 8)
66
@Test	
@Sql(	
scripts="/test-schema.sql",	
config = @SqlConfig(commentPrefix = "`")	
@Sql("/user-data.sql")	
public void userTest() {	
// code that uses the test schema and test data	
}	
Schema uses
custom syntax
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
@Sql wrapped in @SqlGroup (Java 6 & 7)
67
@Test	
@SqlGroup({	
@Sql(	
scripts="/test-schema.sql",	
config = @SqlConfig(commentPrefix = "`"),	
@Sql("/user-data.sql")	
})	
public void userTest() {	
// code that uses the test schema and test data	
}
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Configuring SQL Scripts with @SqlConfig
•  @SqlConfig: configures script parsing and error handling
•  Class-level: serves as global configuration for the test class
•  @Sql(config): serves as local configuration for the enclosing @Sql
•  Local configuration inherits global configuration and can
selectively override global configuration
•  Transaction management for script execution is configured via
the dataSource, transactionManager, and transactionMode
attributes
•  See Javadoc and reference manual for details
68
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
In closing…
69
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Related Sessions @ SpringOne 2GX 2014
70
•  The Quest for the Holy Integration Test
•  Ken Krueger and Rob Winch
•  September 10, 2014
•  4:30 PM - 6:00 PM
•  Building highly modular and testable business systems with
Spring Integration
•  Marius Bogoevici
•  September 11, 2014
•  10:30 AM - 12:00 PM
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Spring Resources
Spring Framework: http://projects.spring.io/spring-framework
Spring Guides: http://spring.io/guides
Spring JIRA: https://jira.spring.io
Spring on GitHub: https://github.com/spring-projects/spring-framework
Stack Overflow: spring, spring-test, spring-mvc, …
71
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Blogs
Spring Blog: http://spring.io/blog
Swiftmind Blog: http://www.swiftmind.com/blog
72
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license
Q & A
Sam Brannen
@sam_brannen
www.slideshare.net/sbrannen
www.swiftmind.com
73
@springcentral | spring.io/video

Testing with Spring 4.x

  • 1.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Unless otherwise indicated, these slides are © 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Testing with Spring 4.x Sam Brannen @sam_brannen
  • 2.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Sam Brannen •  Spring and Java Consultant @ Swiftmind •  Java Developer for over 15 years •  Spring Framework Core Committer since 2007 •  Component lead for spring-test •  Spring Trainer •  Speaker on Spring, Java, and testing •  Swiss Spring User Group Lead 2
  • 3.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Areas of expertise –  Spring * –  Java EE –  Software Architecture –  Software Engineering Best Practices Where you find us •  Zurich, Switzerland •  @swiftmind •  http://www.swiftmind.com 3 Your experts for Spring and Enterprise Java
  • 4.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license A show of hands… 4 ? ? ? ? ?
  • 5.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Agenda •  Deprecations, Pruning, & Dependencies •  Recap of Testing with Spring 3.x •  Testing Themes in 4.x •  Details, Tips, & Examples •  Q&A 5
  • 6.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Deprecations, Pruning, & Dependencies 6
  • 7.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Spring Cleaning in 4.x •  All deprecated packages removed •  Many deprecated methods and fields removed as well •  Mind the deprecation warnings… before upgrading from 3.x 7
  • 8.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Pruning in 4.0 •  JUnit 3.8 support •  Use JUnit 4 or TestNG •  @ExpectedException •  Use @Test(expected) or @Rule ExpectedException in JUnit •  Use @Test(expectedExceptions) in TestNG •  @NotTransactional •  Use @Transactional(propagation=NOT_SUPPORTED) •  SimpleJdbcTestUtils •  Use JdbcTestUtils, ScriptUtils, or @Sql 8
  • 9.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Dependency Upgrades in 4.0 •  Servlet API mocks •  Now based on Servlet 3.0 •  Servlet 2.5 still supported in production •  JUnit •  Tested against à 4.11 •  TestNG •  Tested against à 6.8.5 9
  • 10.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Dependency Upgrades in 4.1 •  JUnit •  Minimum version à 4.9 •  Recommended à 4.11 •  TestNG •  Tested against à 6.8.8 10
  • 11.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Testing with Spring 3.x 11
  • 12.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Testing Themes from Spring 3.x (1/2) •  Embedded databases •  <jdbc:embedded-database /> & <jdbc:initialize-database /> •  EmbeddedDatabaseBuilder & EmbeddedDatabaseFactoryBean •  @Configuration classes •  @ActiveProfiles •  ApplicationContextInitializers 12
  • 13.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Testing Themes from Spring 3.x (2/2) •  @WebAppConfiguration •  Loading WebApplicationContexts •  Testing request- and session-scoped beans •  @ContextHierarchy •  Web, Batch, etc. •  Spring MVC Test framework •  Server-side MVC and REST tests •  Client-side REST tests 13
  • 14.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Web Integration Test (1/2) 14 @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextHierarchy({ @ContextConfiguration(classes = RootConfig.class), @ContextConfiguration(classes = WebConfig.class) }) @ActiveProfiles("dev") public class ControllerIntegrationTests { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; // ...
  • 15.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Web Integration Test (2/2) 15 @Before public void setup() { this.mockMvc = MockMvcBuilders .webAppContextSetup(this.wac).build(); } @Test public void person() throws Exception { this.mockMvc.perform(get("/person/42") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(content().string("{"name":"Sam"}")); }
  • 16.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Testing Themes in Spring 4.0 16
  • 17.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.0 (1/3) •  SocketUtils •  Scan for available UDP & TCP ports •  ActiveProfilesResolver API •  Programmatic alternative to static profile strings •  Set via new resolver attribute in @ActiveProfiles •  Meta-annotation support for tests •  Attribute overrides (optional and required) 17
  • 18.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.0 (2/3) •  New deleteFromTableWhere() method in AbstractTransactional*SpringContextTests •  * à JUnit4 or TestNG •  New verify() and reset() methods in AnnotationDrivenStaticEntityMockingControl •  Multi-line SQL comments: •  ResourceDatabasePopulator, JdbcTestUtils, ScriptUtils 18
  • 19.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.0 (3/3) •  TestContext converted to an interface •  Allows TestContext to be mocked in unit tests •  Simultaneous use of classes and locations in @ContextConfiguration for hybrid loaders •  See Spring Boot •  Servlet API mock improvements 19
  • 20.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Testing Themes in Spring 4.1 20
  • 21.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.1 – Context Config •  Context config with Groovy scripts •  Declarative configuration for test property sources •  @TestPropertySource 21
  • 22.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.1 – Transactions and SQL •  Programmatic test transaction management •  TestTransaction API •  Declarative SQL script execution •  @Sql, @SqlConfig, @SqlGroup •  Improved docs for transactional tests 22
  • 23.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.1 – Bootstrap & TestExecutionListeners •  TestContext bootstrap strategy •  TestContextBootstrapper & @BootstrapWith •  Automatic discovery of default TestExecutionListeners •  Uses SpringFactoriesLoader •  Already used by Spring Security •  Merging custom TestExecutionListeners with defaults •  @TestExecutionListeners(mergeMode=MERGE_WITH_DEFAULTS) •  Defaults to REPLACE_DEFAULTS 23
  • 24.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.1 – Spring MVC Test •  Assert JSON responses with JSON Assert •  Complements JSONPath support •  Create MockMvcBuilder recipes with MockMvcConfigurer •  Developed to apply Spring Security setup but can be used by anyone •  AsyncRestTemplate support in MockRestServiceServer •  For asynchronous client-side testing 24
  • 25.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license New in 4.1 – Odds & Ends •  AssertThrows: refactored to support Throwable •  Various improvements to Servlet API mocks 25
  • 26.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Details, Tips, & Examples 26
  • 27.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license SocketUtils •  Utility class introduced in Spring Framework 4.0 •  Located in spring-core •  Can be used in production code •  But ideal for embedded testing scenarios (SMTP, FTP, etc.) •  Finds available TCP and UDP ports on localhost •  Default port range: 1024 à 65535 •  See Javadoc for all options •  Straightforward usage in Java and @Configuration classes 27
  • 28.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Using SocketUtils in XML Config •  Via fully qualified class name and SpEL <bean id="bean1" ... p:port= "#{T(org.springframework.util.SocketUtils).findAvailableTcpPort(12000)}" /> •  Via socketUtils bean and SpEL (as of Spring 4.0.8 & 4.1.1) <bean id="socketUtils" class="org.springframework.util.SocketUtils" /> <bean id="bean1" ... p:port="#{socketUtils.findAvailableTcpPort(12000)}" /> <bean id="bean2" ... p:port="#{socketUtils.findAvailableTcpPort(30000)}" /> 28
  • 29.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Tip: Define Free Port as Bean •  Define the free port as a Spring Bean… <bean id="serverPort" class="java.lang.Integer" c:_="#{T(socketUtils.findAvailableTcpPort()}" /> •  Then reference the serverPort from other beans •  Or inject it into components, @Configuration classes, and tests 29
  • 30.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: @ActiveProfiles – Declarative 30 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @ActiveProfiles("dev") public class IntegrationTests { // ... } But what if static isn’t good enough?
  • 31.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: @ActiveProfiles – Programmatic 31 public class MyResolver implements ActiveProfilesResolver { public String[] resolve(Class<?> testClass) { // resolve bean definition profiles for test class } } @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @ActiveProfiles(resolver = MyProfileResolver.class) public class IntegrationTests { // ... } Implement custom resolver And declare it
  • 32.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Composable Stereotypes – Quick Review •  Combining meta-annotations on a custom stereotype •  Automatically detected: no configuration necessary! 32
  • 33.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Duplicate Test Configuration == Bad @ContextConfiguration("/test-config.xml") @ActiveProfiles("dev") @Transactional public class OrderRepositoryTests { } @ContextConfiguration("/test-config.xml") @ActiveProfiles("dev") @Transactional public class UserRepositoryTests { } 33 duplication duplication
  • 34.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Custom Test Annotation == Good @Target(TYPE) @Retention(RUNTIME) @ContextConfiguration("/test-config.xml") @ActiveProfiles("dev") @Transactional public @interface TransactionalDevTest { } @TransactionalDevTest public class OrderRepositoryTests { } @TransactionalDevTest public class UserRepositoryTests { } 34 common config
  • 35.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Composable Annotations with Overrides •  Composable annotations may override attributes of meta- annotations •  Purely convention-based •  Matched by attribute name and type •  Can lead to potential naming conflicts •  Cannot override the value attribute 35
  • 36.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Optional Annotation Attribute Override @Target(TYPE) @Retention(RUNTIME) @ContextConfiguration @Transactional public @interface TransactionalTest { String[] locations() default "/test-config.xml"; } @TransactionalTest(locations = "/order-test-config.xml") public class OrderRepositoryTests { } 36 optional: overrides default default locations declared here will be ignored
  • 37.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Required Annotation Attribute Override @Target(TYPE) @Retention(RUNTIME) @ContextConfiguration @Transactional public @interface TransactionalTest { String[] locations(); } @TransactionalTest(locations = "/order-test-config.xml") public class OrderRepositoryTests { } 37 required no default locations declared here will be ignored
  • 38.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Groovy Beans in Spring •  Spring Framework 4.0 introduced support for the Groovy Bean Definition DSL via the GroovyBeanDefinitionReader and GenericGroovyApplicationContext •  Spring Framework 4.1 introduces support for Groovy scripts in web applications via the GroovyWebApplicationContext •  Testing support added in 4.1… 38
  • 39.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Spring Bean Definitions with Groovy DSL import org.mypackage.domain.Person; beans { xmlns util: 'http://www.springframework.org/schema/util' person1(Person) { name = "homer" age = 45 props = [overweight: true, height: "1.8m"] children = ["bart", "lisa"] } util.list(id: 'foo') { value 'one' value 'two' } } 39
  • 40.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Groovy Scripts for Context Config in Tests •  Spring Framework 4.1 introduces support for Groovy scripts in integration tests via @ContextConfiguration •  Scripts are configured via the locations or value attribute o  Resource semantics identical to XML o  Default detected with “Context.groovy” suffix in same package •  The inheritLocations flag is fully supported •  Groovy and XML configuration can be declared together •  Groovy WebApplicationContexts supported via @WebAppConfiguration 40
  • 41.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Groovy Script Config @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/context.groovy") public class GroovyPersonTests { @Autowired private Person person; /* test methods using person bean */ } 41
  • 42.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Default Groovy Script Detection public com.example; @RunWith(SpringJUnit4ClassRunner.class) // ApplicationContext will be loaded from // “classpath:com/example/MyTestContext.groovy” @ContextConfiguration public class MyTest { /* ... */ } 42
  • 43.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Groovy & XML Config Together @RunWith(SpringJUnit4ClassRunner.class) // ApplicationContext will be loaded from // “/context.groovy” and “/context.xml” @ContextConfiguration({ "/context.groovy", "/context.xml" }) public class MyTest { /* ... */ } 43
  • 44.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Test Property Sources •  Spring 3.1 introduced PropertySources abstraction •  Configured via Environment or via @PropertySource •  Spring 4.1 supports declarative test property sources •  Configured via @TestPropertySource •  Test property sources are declared via annotation attributes •  locations or value: resource locations •  properties: inlined properties •  both are inherited by default 44
  • 45.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license @TestPropertySource – locations •  String array of resource locations for Java Properties files •  Both traditional *.properties and XML formats are supported •  Resource semantics are identical to those for locations in @ContextConfiguration 45
  • 46.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: @TestPropertySource – locations @ContextConfiguration @TestPropertySource("/test.properties") public class MyIntegrationTests { // class body... } 46
  • 47.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license @TestPropertySource – properties •  Inlined properties can be declared as key/value pairs •  Uses syntax for entries in Java properties files: •  "key=value" •  "key:value" •  "key value" 47
  • 48.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: @TestPropertySource – properties @ContextConfiguration @TestPropertySource( properties = {"foo=bar", "port: 4242"} ) public class MyIntegrationTests { // class body... } 48
  • 49.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Default Properties File Detection •  If neither locations nor properties are defined, a default properties file will be detected •  Default is detected with “.properties” suffix in same package •  If the class is com.example.MyTest, the default properties file is “classpath:com/example/MyTest.properties” •  Exception is thrown if default is not present 49
  • 50.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license @TestPropertySource – Precedence 50 Inlined Files Application & System test precedence
  • 51.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: @TestPropertySource – locations & properties @ContextConfiguration @TestPropertySource( locations = "/test.properties", properties = "port: 4242" ) public class MyIntegrationTests { // class body... } 51
  • 52.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Programmatic Transaction Management in Tests •  History Lesson: Spring’s JUnit 3.8 testing framework supported endTransaction() and startNewTransaction() methods in AbstractTransactionalSpringContextTests •  But… the Spring TestContext Framework, introduced in Spring 2.5, did not… until now •  Due to popular demand, Spring 4.1 introduces a new TestTransaction API 52
  • 53.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Transactions in Spring •  Spring-managed transactions: managed by Spring in the ApplicationContext •  @Transactional and AOP •  Application-managed transactions: managed programmatically within application code •  TransactionTemplate and TransactionSynchronizationManager •  Test-managed transactions: managed by the Spring TestContext Framework •  @Transactional on test classes and test methods •  Transaction is rolled back by default! 53
  • 54.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Declarative Transaction Management in Tests @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @Transactional public class TransactionalTests { @Test public void withinTransaction() { /* ... */ } 54 What if we want to stop & start the transaction within the test method?
  • 55.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license TestTransaction API •  Static methods for interacting with test-managed transactions •  isActive() •  isFlaggedForRollback() •  flagForCommit() •  flagForRollback() •  end() •  start() 55 query status change default rollback setting end: roll back or commit based on flag start: new tx with default rollback setting
  • 56.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Programmatic Transaction Management in Tests @Test public void withinTransaction() { // assert initial state in test database: assertNumUsers(2); deleteFromTables("user"); // changes to the database will be committed TestTransaction.flagForCommit(); TestTransaction.end(); assertFalse(TestTransaction.isActive()); assertNumUsers(0); TestTransaction.start(); // perform other actions against the database that will // be automatically rolled back after the test completes... } 56
  • 57.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Executing SQL Scripts 57
  • 58.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Embedded Database in Java Config 58 @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("schema.sql") .addScripts("user_data.sql", "country_data.sql") .build(); } API greatly improved in Spring 4.0.3
  • 59.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Embedded Database in XML Config <jdbc:embedded-database id="dataSource" type="H2"> <jdbc:script location="classpath:/schema.sql" /> <jdbc:script location="classpath:/user_data.sql" /> </jdbc:embedded-database> 59
  • 60.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: Populate Database in XML Config <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:/schema_01.sql" /> <jdbc:script location="classpath:/schema_02.sql" /> <jdbc:script location="classpath:/data_01.sql" /> <jdbc:script location="classpath:/data_02.sql" /> </jdbc:initialize-database> 60
  • 61.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Executing SQL per Test Method •  The previous techniques are very useful for setting up the initial database state •  Q: But how can we execute SQL scripts per test method? •  A: Programmatically via ScriptUtils, ResourceDatabasePopulator, or abstract transactional base test classes for JUnit and TestNG. •  Q: OK, but how can we do that declaratively? •  A: Via @Sql in Spring Framework 4.1! 61
  • 62.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Executing SQL Scripts Declaratively with @Sql •  @Sql: declared on a test class or test method •  method-level overrides class-level •  The scripts attribute is used to declare resource locations for SQL scripts •  semantics analogous to locations in @ContextConfiguration •  Scripts can be executed before or after a test method •  configured via the executionPhase attribute of @Sql 62
  • 63.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Ex: @Sql in Action @ContextConfiguration @Sql({ "schema1.sql", "data1.sql" }) public class SqlScriptsTests { @Test public void classLevelScripts() { /* ... */ } @Test @Sql({ "schema2.sql", "data2.sql" }) public void methodLevelScripts() { /* ... */ } 63
  • 64.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Default SQL Script Detection •  If no scripts are declared, a default script will be detected •  Depending on where @Sql is declared •  Class-level: for com.example.DbTest, the default is “classpath:com/ example/DbTest.sql” •  Method-level: for com.example.DbTest.test(), the default is “classpath:com/example/DbTest.test.sql” •  If the default is not present, an exception is thrown 64
  • 65.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Declaring Multiple @Sql Sets •  Declare multiple sets of @Sql scripts for varying configuration •  Java 8: use @Sql as a repeatable annotation •  Java 6 & 7: wrap @Sql sets in @SqlGroup 65
  • 66.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license @Sql as a Repeatable Annotation (Java 8) 66 @Test @Sql( scripts="/test-schema.sql", config = @SqlConfig(commentPrefix = "`") @Sql("/user-data.sql") public void userTest() { // code that uses the test schema and test data } Schema uses custom syntax
  • 67.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license @Sql wrapped in @SqlGroup (Java 6 & 7) 67 @Test @SqlGroup({ @Sql( scripts="/test-schema.sql", config = @SqlConfig(commentPrefix = "`"), @Sql("/user-data.sql") }) public void userTest() { // code that uses the test schema and test data }
  • 68.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Configuring SQL Scripts with @SqlConfig •  @SqlConfig: configures script parsing and error handling •  Class-level: serves as global configuration for the test class •  @Sql(config): serves as local configuration for the enclosing @Sql •  Local configuration inherits global configuration and can selectively override global configuration •  Transaction management for script execution is configured via the dataSource, transactionManager, and transactionMode attributes •  See Javadoc and reference manual for details 68
  • 69.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license In closing… 69
  • 70.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Related Sessions @ SpringOne 2GX 2014 70 •  The Quest for the Holy Integration Test •  Ken Krueger and Rob Winch •  September 10, 2014 •  4:30 PM - 6:00 PM •  Building highly modular and testable business systems with Spring Integration •  Marius Bogoevici •  September 11, 2014 •  10:30 AM - 12:00 PM
  • 71.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Spring Resources Spring Framework: http://projects.spring.io/spring-framework Spring Guides: http://spring.io/guides Spring JIRA: https://jira.spring.io Spring on GitHub: https://github.com/spring-projects/spring-framework Stack Overflow: spring, spring-test, spring-mvc, … 71
  • 72.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Blogs Spring Blog: http://spring.io/blog Swiftmind Blog: http://www.swiftmind.com/blog 72
  • 73.
    © 2012-2014 SamBrannen and licensed under a Creative Commons Attribution-NonCommercial license Q & A Sam Brannen @sam_brannen www.slideshare.net/sbrannen www.swiftmind.com 73 @springcentral | spring.io/video