Testing with Spring: An Introduction
-
Upload
sam-brannen -
Category
Software
-
view
642 -
download
2
Transcript of Testing with Spring: An Introduction
![Page 1: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/1.jpg)
Testing with Spring: An Introduction Sam Brannen @sam_brannen
Spring eXchange | London, England | November 6, 2014
eXchange 2014
![Page 2: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/2.jpg)
2
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
![Page 3: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/3.jpg)
3
Swiftmind
Experts in Spring and Enterprise Java Areas of expertise • Spring * • Java EE • Software Architecture • Software Engineering Best Practices
Where you find us • Zurich, Switzerland • @swiftmind • http://www.swiftmind.com
![Page 4: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/4.jpg)
4
A Show of Hands…
? ? ?
?
![Page 5: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/5.jpg)
5
Agenda
• Unit testing
• Integration testing
• Context management and DI
• Transactions and SQL scripts
• Spring MVC and REST
• Q&A
![Page 6: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/6.jpg)
6
Unit Testing
![Page 7: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/7.jpg)
7
Unit Tests
• are simple to set up
• use dynamic mocks or stubs for dependencies
• instantiate the SUT, execute the code, and assert expectations
• run fast
• but only test a single unit
![Page 8: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/8.jpg)
8
Spring and Unit Testing
• POJO-based programming model – Program to interfaces – IoC / Dependency Injection – Out-of-container testability – Third-party mocking frameworks (Mockito, …)
• Spring testing mocks/stubs – Servlet – Portlet – JNDI – Spring Environment
![Page 9: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/9.jpg)
9
EventService API
public interface EventService {
List<Event> findAll();
Event save(Event event);
void delete(Event event);}
![Page 10: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/10.jpg)
10
EventService Implementation (1/2)
@Service@Transactionalpublic class StandardEventService implements EventService {
private final EventRepository repository;
@Autowired public StandardEventService(EventRepository repository) { this.repository = repository; }
// ...
![Page 11: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/11.jpg)
11
EventService Implementation (2/2)
public Event save(final Event event) {
// additional business logic ...
return repository.save(event);}
![Page 12: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/12.jpg)
12
EventService Unit Test (1/2)
public class StandardEventServiceTests {
private StandardEventService service; private EventRepository repository;
@Before public void setUp() { repository = mock(EventRepository.class); service = new StandardEventService(repository); }
![Page 13: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/13.jpg)
13
EventService Unit Test (2/2)
@Testpublic void save() { Event event = new Event(); event.setName("test event"); event.setDescription("testing");
given(repository.save(any(Event.class))) .willReturn(event);
Event savedEvent = service.save(event); assertThat(savedEvent, is(equalTo(event)));}
![Page 14: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/14.jpg)
14
Integration Testing
![Page 15: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/15.jpg)
15
Integration Tests
• test interactions between multiple components
• relatively easy to set up… • without external system dependencies
• challenging to set up… • with external system dependencies
• more challenging… • if application code depends on the container
![Page 16: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/16.jpg)
16
Integration Test Complexity
Complexity
Dependency no external systems
external systems
container
![Page 17: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/17.jpg)
17
Modern Enterprise Java Apps
• Integrate with external systems • SMTP, FTP, LDAP, RDBMS, Web Services, JMS
• Rely on container-provided functionality • data sources, connection factories, transaction
managers
![Page 18: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/18.jpg)
18
Effective Integration Testing
• Fast
• Repeatable
• Automated
• Easy to configure
• Run out-of-container
![Page 19: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/19.jpg)
19
Out-of-container
• Zero reliance on availability of external systems
• Can be run anywhere • developer workstation • CI server
• Approximate the production environment • Embedded database • In-memory SMTP server, FTP server, JMS broker
![Page 20: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/20.jpg)
20
Spring TestContext Framework
![Page 21: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/21.jpg)
21
In a nutshell…
The Spring TestContext Framework … provides annotation-driven unit and integration testing support that is agnostic of the testing framework in use … with a strong focus on convention over configuration and reasonable defaults that can be overridden through annotation-based configuration … and integrates with JUnit and TestNG out of the box.
![Page 22: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/22.jpg)
22
Testimony
“The Spring TestContext Framework is an excellent example of good annotation usage as it allows composition rather than inheritance.” - Costin Leau
![Page 23: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/23.jpg)
23
Feature Set
• Context management and caching
• Dependency Injection of test fixtures
• Transaction management
• SQL script execution
• Spring MVC and REST
• Extension points for customization
![Page 24: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/24.jpg)
24
Spring 2.5 Testing Themes
• @ContextConfiguration – XML config files – Context caching
• @TestExecutionListeners – Dependency injection: @Autowired, etc. – @DirtiesContext – @Transactional, @BeforeTransaction, etc.
• SpringJUnit4ClassRunner
• Abstract base classes for JUnit and TestNG
![Page 25: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/25.jpg)
25
Spring 3.x Testing Themes (1/2)
• Embedded databases – <jdbc:embedded-database /> &
<jdbc:initialize-database /> – EmbeddedDatabaseBuilder &
EmbeddedDatabaseFactoryBean
• @Configuration classes
• @ActiveProfiles
• ApplicationContextInitializers
![Page 26: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/26.jpg)
26
Spring 3.x Testing Themes (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
![Page 27: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/27.jpg)
27
Spring 4.0 Testing Themes
• SocketUtils – Scan for available UDP & TCP ports
• ActiveProfilesResolver API – Programmatic alternative to static profile strings – Set via resolver attribute in @ActiveProfiles
• Meta-annotation support for tests – Attribute overrides (optional and required)
![Page 28: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/28.jpg)
28
New in 4.1 – Context Config
• Context config with Groovy scripts
• Declarative configuration for test property sources
– @TestPropertySource
![Page 29: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/29.jpg)
29
New in 4.1 – Transactions & SQL
• Programmatic test transaction management – TestTransaction API
• Declarative SQL script execution – @Sql, @SqlConfig, @SqlGroup
• Improved docs for transactional tests
![Page 30: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/30.jpg)
30
New in 4.1 – TestExecutionListeners
• 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
![Page 31: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/31.jpg)
31
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
![Page 32: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/32.jpg)
32
Context Management
![Page 33: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/33.jpg)
33
@ContextConfiguration
• Declared on test class – Inheritance supported but overridable – Spring Boot: use @SpringApplicationConfiguration
• ContextLoader loads ApplicationContext based on: – Configuration in annotation – Or by detecting default configuration
• Supports: – XML configuration files – @Configuration classes – Groovy scripts
![Page 34: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/34.jpg)
34
@WebAppConfiguration
• Declared on test class
• Instructs Spring to load a WebApplicationContext for the test
• ServletTestExecutionListener ensures that Servlet API mocks are properly configured
• Most often used with the Spring MVC Test Framework
![Page 35: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/35.jpg)
35
@ContextHierarchy
• Declared on test class – Used with @ContextConfiguration
• Configures hierarchies of test application contexts – Useful for Spring MVC, Spring Batch, etc.
![Page 36: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/36.jpg)
36
@ActiveProfiles
• Declared on test class – Used with @ContextConfiguration
• Configures which bean definition profiles should be active when the test’s ApplicationContext is loaded
• Active profiles can be configured: – Declaratively within the annotation – Or programmatically via a custom ActiveProfilesResolver
![Page 37: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/37.jpg)
37
Context Caching
• The Spring TestContext Framework caches all application contexts within the same JVM process!
• Cache key is generated based on configuration in: – @ContextConfiguration – @ContextHierarchy – @WebAppConfiguration – @ActiveProfiles
• Use @DirtiesContext to remove a given test from the cache
![Page 38: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/38.jpg)
38
Ex: Context Configuration
@RunWith(SpringJUnit4ClassRunner.class)@WebAppConfiguration@ContextHierarchy({
@ContextConfiguration(classes = RootConfig.class),@ContextConfiguration(classes = WebConfig.class)
})@ActiveProfiles("dev")public class ControllerIntegrationTests {
// ...
![Page 39: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/39.jpg)
39
Dependency Injection
![Page 40: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/40.jpg)
40
DI within Integration Tests
• Dependencies can be injected into a test instance from the test’s ApplicationContext • Using @Autowired, @Inject, @PersistenceContext, etc.
• The ApplicationContext itself can also be injected into test instances… • @Autowired ApplicationContext • @Autowired WebApplicationContext
![Page 41: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/41.jpg)
41
EventService Integration Test
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfigurationpublic class EventServiceIntegrationTests {
@Autowired EventService service;
@Test public void save() { Event event = new Event("test event"); Event savedEvent = service.save(event); assertNotNull(savedEvent.getId()); // ...}
![Page 42: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/42.jpg)
42
Transactional Tests
![Page 43: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/43.jpg)
43
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!
![Page 44: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/44.jpg)
44
Ex: Declarative Tx Management in Tests
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration@Transactionalpublic class TransactionalTests {
@Test public void withinTransaction() { /* ... */ } What if we want to
stop & start the transaction within the test method?
![Page 45: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/45.jpg)
45
TestTransaction API
• Static methods for interacting with test-managed transactions
– isActive() – isFlaggedForRollback()
– flagForCommit() – flagForRollback()
– end() – start()
query status
change default rollback setting
end: roll back or commit based on flag start: new tx with default rollback setting
![Page 46: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/46.jpg)
46
Ex: Programmatic Tx Mgmt 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(); assertNumUsers(0);
TestTransaction.start(); // perform other actions against the database that will // be automatically rolled back after test completes...}
![Page 47: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/47.jpg)
47
SQL Script Execution
![Page 48: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/48.jpg)
48
SQL Script Execution Options
• At ApplicationContext startup via: • <jdbc> XML namespace • EmbeddedDatabaseBuilder in Java Config
• Programmatically during tests with: • ScriptUtils, ResourceDatabasePopulator, or abstract
transactional base test classes for JUnit and TestNG
• Declaratively via @Sql, @SqlConfig, & @SqlGroup • Per test method • Per test class
![Page 49: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/49.jpg)
49
Ex: Embedded Database in Java Config
EmbeddedDatabase db = new EmbeddedDatabaseBuilder() .setType(H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("schema.sql") .addScripts("user_data.sql", "country_data.sql") .build();
// ...
db.shutdown();
![Page 50: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/50.jpg)
50
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>
![Page 51: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/51.jpg)
51
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>
![Page 52: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/52.jpg)
52
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() { /* ... */ }
![Page 53: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/53.jpg)
53
@Sql - Repeatable Annotation (Java 8)
@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 54: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/54.jpg)
54
@Sql wrapped in @SqlGroup (Java 6/7)
@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 55: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/55.jpg)
55
Spring MVC Test Framework
![Page 56: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/56.jpg)
56
What is Spring MVC Test?
• Dedicated support for testing Spring MVC applications
• Fluent API
• Very easy to write
• Includes client and server-side support
• Servlet container not required
![Page 57: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/57.jpg)
57
Details
• Included in spring-test module of Spring Framework 3.2
• Builds on
– TestContext framework for loading Spring MVC configuration
– MockHttpServlet[Request|Response] and other mock types
• Server-side tests involve DispatcherServlet
• Client-side REST testing for code using RestTemplate
![Page 58: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/58.jpg)
58
Ex: Web Integration Test (1/2) @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 59: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/59.jpg)
59
Ex: Web Integration Test (2/2) @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 60: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/60.jpg)
60
In Closing…
![Page 61: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/61.jpg)
61
Spring Resources
• Spring Framework – http://projects.spring.io/spring-framework
• Spring Guides – http://spring.io/guides
• Spring Forums – http://forum.spring.io
• Spring JIRA – https://jira.spring.io
• Spring on GitHub – https://github.com/spring-projects/spring-framework
![Page 62: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/62.jpg)
62
Blogs
• Swiftmind Blog – http://www.swiftmind.com/blog
• Spring Blog – http://spring.io/blog
![Page 63: Testing with Spring: An Introduction](https://reader034.fdocuments.in/reader034/viewer/2022042702/55d58ff5bb61eb6b498b45de/html5/thumbnails/63.jpg)
63
Q & A
Sam Brannen twitter: @sam_brannen www.slideshare.net/sbrannen www.swiftmind.com