testing with spring framework 4.x
DESCRIPTION
Speaker: Sam Brannen Core Spring Track The Spring Framework has undergone a lot of innovation in the 4.0 and 4.1 releases, and so has its testing support. Join Spring Test component lead Sam Brannen in this talk to discover what's new in Spring's testing support in 4.0 through 4.1. This talk will provide attendees an overview of what's been deprecated, what's changed, and what's been introduced in Spring's testing support over the last two years, with real life examples and tips for best practices. Highlights include using SocketUtils to scan for free TCP & UDP server ports, the ActiveProfilesResolver API, meta-annotation support for test annotations including attribute overrides, best practices with TestNG, using Groovy scripts to configure an ApplicationContext for integration tests, improvements to SQL script execution and embedded databases, the new TestContext framework bootstrap strategy, programmatic transaction management in tests, and more.TRANSCRIPT
![Page 1: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/1.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense Unless otherwise indicated, these slides are © 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense: http://creativecommons.org/licenses/by-nc/3.0/
Testing with Spring 4.x Sam Brannen @sam_brannen
![Page 2: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/2.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 3: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/3.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 4: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/4.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
A show of hands…
4
?
? ?
?
?
![Page 5: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/5.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Agenda
• Deprecations, Pruning, & Dependencies
• Recap of Testing with Spring 3.x
• Testing Themes in 4.x
• Details, Tips, & Examples
• Q&A
5
![Page 6: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/6.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Deprecations, Pruning, & Dependencies
6
![Page 7: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/7.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 8: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/8.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 9: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/9.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 10: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/10.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Dependency Upgrades in 4.1
• JUnit • Minimum version à 4.9 • Recommended à 4.11
• TestNG • Tested against à 6.8.8
10
![Page 11: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/11.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing with Spring 3.x
11
![Page 12: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/12.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing Themes from Spring 3.x (1/2)
• Embedded databases • <jdbc:embedded-database /> & <jdbc:initialize-database /> • EmbeddedDatabaseBuilder & EmbeddedDatabaseFactoryBean
• @Configuration classes
• @ActiveProfiles
• ApplicationContextInitializers
12
![Page 13: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/13.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 14: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/14.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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; // ...
![Page 15: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/15.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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\"}")); }
![Page 16: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/16.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing Themes in Spring 4.0
16
![Page 17: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/17.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 18: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/18.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 19: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/19.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 20: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/20.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Testing Themes in Spring 4.1
20
![Page 21: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/21.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.1 – Context Config
• Context config with Groovy scripts
• Declarative configuration for test property sources
• @TestPropertySource
21
![Page 22: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/22.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 23: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/23.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 24: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/24.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 25: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/25.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
New in 4.1 – Odds & Ends
• AssertThrows: refactored to support Throwable
• Various improvements to Servlet API mocks
25
![Page 26: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/26.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Details, Tips, & Examples
26
![Page 27: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/27.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 28: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/28.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 29: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/29.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 30: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/30.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @ActiveProfiles – Declarative
30
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration@ActiveProfiles("dev")public class IntegrationTests { // ...}
But what if static isn’t good enough?
![Page 31: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/31.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 32: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/32.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Composable Stereotypes – Quick Review
• Combining meta-annotations on a custom stereotype • Automatically detected: no configuration necessary!
32
![Page 33: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/33.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Duplicate Test Configuration == Bad
@ContextConfiguration("/test-config.xml")@ActiveProfiles("dev")@Transactionalpublic class OrderRepositoryTests {}@ContextConfiguration("/test-config.xml")@ActiveProfiles("dev")@Transactionalpublic class UserRepositoryTests {}
33
duplication
duplication
![Page 34: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/34.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Custom Test Annotation == Good
@Target(TYPE)@Retention(RUNTIME)@ContextConfiguration("/test-config.xml")@ActiveProfiles("dev")@Transactionalpublic @interface TransactionalDevTest { }@TransactionalDevTestpublic class OrderRepositoryTests { }@TransactionalDevTestpublic class UserRepositoryTests { }
34
common config
![Page 35: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/35.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 36: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/36.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Optional Annotation Attribute Override
@Target(TYPE)@Retention(RUNTIME)@ContextConfiguration@Transactionalpublic @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
![Page 37: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/37.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Required Annotation Attribute Override
@Target(TYPE)@Retention(RUNTIME)@ContextConfiguration@Transactionalpublic @interface TransactionalTest {
String[] locations();}@TransactionalTest(locations = "/order-test-config.xml")public class OrderRepositoryTests { }
37
required
no default
locations declared here will be ignored
![Page 38: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/38.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 39: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/39.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 40: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/40.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 41: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/41.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Groovy Script Config
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("/context.groovy")public class GroovyPersonTests { @Autowired private Person person; /* test methods using person bean */}
41
![Page 42: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/42.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Default Groovy Script Detection
public com.example;@RunWith(SpringJUnit4ClassRunner.class)// ApplicationContext will be loaded from// “classpath:com/example/MyTestContext.groovy”@ContextConfigurationpublic class MyTest { /* ... */}
42
![Page 43: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/43.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 44: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/44.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 45: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/45.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@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
![Page 46: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/46.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @TestPropertySource – locations
@ContextConfiguration@TestPropertySource("/test.properties")public class MyIntegrationTests {
// class body...}
46
![Page 47: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/47.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@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
![Page 48: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/48.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @TestPropertySource – properties
@ContextConfiguration@TestPropertySource( properties = {"foo=bar", "port: 4242"})public class MyIntegrationTests {
// class body...}
48
![Page 49: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/49.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 50: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/50.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@TestPropertySource – Precedence
50
Inlined
Files
Application & System
test
prec
eden
ce
![Page 51: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/51.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: @TestPropertySource – locations & properties
@ContextConfiguration@TestPropertySource( locations = "/test.properties", properties = "port: 4242")public class MyIntegrationTests {
// class body...}
51
![Page 52: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/52.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 53: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/53.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 54: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/54.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Declarative Transaction Management in Tests
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration@Transactionalpublic class TransactionalTests { @Test public void withinTransaction() { /* ... */ }
54
What if we want to stop & start the
transaction within the test method?
![Page 55: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/55.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 56: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/56.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Programmatic Transaction Management in Tests
@Testpublic 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
![Page 57: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/57.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Executing SQL Scripts
57
![Page 58: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/58.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Ex: Embedded Database in Java Config
58
@Beanpublic 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
![Page 59: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/59.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 60: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/60.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 61: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/61.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 62: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/62.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 63: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/63.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 64: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/64.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 65: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/65.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 66: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/66.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@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
![Page 67: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/67.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
@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}
![Page 68: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/68.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 69: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/69.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
In closing…
69
![Page 70: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/70.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 71: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/71.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
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
![Page 72: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/72.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Blogs
Spring Blog: http://spring.io/blog Swiftmind Blog: http://www.swiftmind.com/blog
72
![Page 73: Testing with Spring Framework 4.x](https://reader031.vdocuments.mx/reader031/viewer/2022020207/559444b41a28ab01308b4800/html5/thumbnails/73.jpg)
© 2012-2014 Sam Brannen and licensed under a Creative Commons Attribution-NonCommercial l icense
Q & A Sam Brannen
@sam_brannen
www.slideshare.net/sbrannen
www.swiftmind.com
73
@springcentral | spring.io/video