Learn Scala with Specs2 Spring

Use Scala code to safely test and debug Spring-based Java apps

1 2 Page 2
Page 2 of 2

The Specs2 Spring code in Listing 4 handled much of our test setup with very little code. The the body of the specification ("Generate 10 riders") also leveraged some helpful features of Specs2. Specs2 Spring prepared the JNDI environment for the test and instantiated the Spring ApplicationContext, then it injected the RiderManager instance into the RiderManagerSpec.

Listing 5 shows the testing portion of code from Listing 4. Note that the Specs2 code, written in Scala, is shorter and clearer than Java code, while still expressing the same test.

Listing 5. The testing code

...
    class RiderManagerSpec extends Specification {
        ...
    
        "Generate 10 riders" in {
            val count = 10
            this.riderManager.generate(count)
            this.riderManager.findAll.size() must be_==(count)
        }

    }

The "Generate 10 riders" specification's body clearly expresses what is being tested with as little syntactic noise as possible. Instead of Java's cumbersome Assert.assertThat(this.riderManager.findAll.size(), CoreMatchers.is(count)), Scala gave us: this.riderManager.findAll.size() must be_==(count). (Using static imports in Java would be another way to get at more elegant syntax, but I feel that it is still far too verbose; e.g., assertThat(this.riderManager.findAll.size(), is(count)).)

Running parallel examples in Specs2

In some cases you will want to run more than one test (or example in Specs2) in a specification. It should be possible to run the examples in parallel, in multiple threads. So, suppose that we have two examples in our RiderManagerSpec, and that both of them would modify the database. If we run both examples in parallel, it will be difficult to ensure that they do not influence each other. We don't want to lose the parallel nature of Specs2, but we do want to isolate every test example. This is a problem for transactional semantics!

It is easy to modify the specification to run every example in its transaction and then roll back that transaction when the example finishes, as shown in Listing 6.

Listing 6. Transactional example semantics

@Transactional
    @DataSource(name = "java:comp/env/jdbc/test",
        driverClass = classOf[JDBCDriver], url = "jdbc:hsqldb:mem:test")
    @TransactionManager(name = "java:comp/TransactionManager")
    @ContextConfiguration(Array("classpath*:/META-INF/spring/module-context.xml"))
    class RiderManagerSpec extends Specification {
        ...
    }

Notice the @Transactional annotation on the specification. When Specs2 Spring sees this annotation, it will look for a PlatformTransactionManager bean in the Spring context constructed for the test. It will then use that PlatformTransactionManager to wrap the example in a transaction. It will automatically roll back the completed transaction, regardless of whether it completed successfully or failed.

Now let's take a quick look at what Specs2 Spring does to simplify writing acceptance specifications.

Acceptance specifications in Specs2 Spring Web

Version 1.0 of Specs2 Spring will support acceptance testing of servlet-based applications. This will include web applications that interact with browsers or other systems and use DispatcherServlet or the MessageDispatcherServlet. Specs2 Spring Web will enable developers to write specifications that can verify the behavior of the entire system, including its interface. At the same time, it will let specifications access the underlying structure of the application. Listing 7 shows an acceptance specification in Specs2 Spring.

Listing 7. Acceptance specification

@WebContextConfiguration(
        webContextLocations = Array("/WEB-INF/sw-servlet.xml"),
        contextLocations = Array("classpath*:/META-INF/spring/module-context.xml"))
    @DataSource(name = "java:comp/env/jdbc/test",
        driverClass = classOf[JDBCDriver], url = "jdbc:hsqldb:mem:test")
    @TransactionManager(name = "java:comp/TransactionManager")
    class IndexControllerTest extends Specification {
        @Autowired var riderManager: RiderManager = _

        "web roundtrip test" in {
            val rider = new Rider()
            rider.setUsername("aaaa")
            rider.setFullName("Jan")
            Json(put)("/riders.json", rider)

            val savedRider = riderManager.getByUsername("aaaa")
            val wo = Xhtml(get)("/riders/" + savedRider.getId + ".html")

            Xhtml(post)((wo!) << ("#fullName", "Edited Jan"))

            riderManager.getByUsername("aaaa").getFullName must_== ("Edited Jan")
        }

    }

The code in Listing 7 verifies that the system can accept an HTTP PUT to the /riders.html URL with some parameters. On receiving the PUT request, I verify that the system inserts the rider object specified in the parameters of the request. Once inserted, I verify that the system can also execute the HTTP GET request to load the newly created rider.

The result of loading the rider is an XHTML document. In order to verify that the document contains the correct information, I use a jQuery-style selector to modify the value of the input element with the id fullName. Once I have the XHTML document, I'll verify the HTTP POST of the XHTML form, which should result in an update to the rider object. Finally I'll check that the system has correctly saved the edits to the Rider object.

In conclusion

If you're already a Spring developer and you've been curious about incorporating Scala's functional programming features into your applications, then you can start by implementing your test code in Scala. Doing so will help you learn the patterns of object-functional programming without committing beginner code to your main code base. Specs2 Spring is a solid testing framework and could be a good starting point for this approach to learning Scala.

Jan Machacek is the technical director of Cake Solutions. He is a highly experienced Java enterprise architect, consultant, and developer with strong technical and team management skills. Jan has led teams through the perils of agile software delivery, bringing control and value to businesses and the joy of programming to technical teams. Alongside several articles, Jan has authored four books, including Pro Spring and Pro Spring 2.5. He regularly speaks at conferences and developer events in the UK and abroad and is the editor of the Open Source Journal. Jan leads three open source projects: Specs2 Spring, Spock Spring Integration, and Scalad. In his spare time, Jan competes in time trials and road races as a member of the Manchester Wheelers' Cycling Club.

Learn more about this topic

  • Specs2 Spring is a Specs2 extension for BDD & testing typical Spring enterprise applications in Scala.
  • The Spring framework is a de-facto standard for implementing loosely-coupled, flexible, and testable Java EE applications.
  • Specs2 is a Scala BDD testing framework.
  • Scala is a strongly-typed object-functional scalable language.
  • "Dependency injection vs. Cake pattern" (Cake Solutions Team Blog, December 15, 2011): Learn more about the cake pattern as an alternative to dependency injection, as it is implemented in several web application frameworks.

More from JavaWorld

1 2 Page 2
Page 2 of 2