AiL – JBehave and Spring

Having succeeded in getting a simple JBehave story running. my next challenge is to scale it up a bit. In particular, I want to get a JBehave story that integrates with Spring to do something more fully-featured: save an entry in a database.

Because I don’t yet trust JBehave enough to let it drive my application, I’ll back up this with a conventional JUnit test – that will let me know that the story is doing what its meant to do.

To start with, I copied the Simple JBehave scenario from last time, just to get things moving. I then created a simple database app, using a gist I’d prepared a while ago as a template. At this point, the app doesn’t do anything – it’s just a single persistent class.

@Entity @Table
public class Foo {
    @Id @GeneratedValue(strategy = AUTO)
    private long id;

    @Column(length = 50, nullable = false, unique = true)
    private String name;

    @Column(length = 200, nullable = true)
    private String description;

    Foo() {
        // for hibernate.
    }

    public Foo(String name) {
        this.name = name;
    }

    public long getId() { return id; }
    public String getName() { return name; }

    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
}

I want to augment this with a simple service that I’ll write the JBehave story for.  So the next step is to create the service.

@Repository
public class FooService {
    @Autowired
    private SessionFactory sessionFactory;

    @Transactional
    public void createFoo(String name, String description) {
        Foo foo = new Foo(name);
        foo.setDescription(description);
        sessionFactory.getCurrentSession().save(foo);
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testContext.xml")
public class FooServiceTest {

    @Autowired private FooService test;
    @Autowired private JdbcTemplate jdbc;

    @After public void cleanData() {
        jdbc.execute("truncate schema PUBLIC and commit");
    }

    @Test public void test() {
        assertEquals("we start with no foo", 0, jdbc.queryForInt("select count(*) from foo"));

        test.createFoo("foo", "this is a test foo");

        assertEquals("we end with one foo", 1, jdbc.queryForInt("select count(*) from foo"));

        Map results = jdbc.queryForMap("select * from foo");
        assertEquals("foo", results.get("name"));
        assertEquals("this is a test foo", results.get("description"));
    }
}

Again, this is a really simple test, but it’s a good starting point. I need to make sure that the JBehave test that I write can cover this as well.

(A key thing to note here: the FooServiceTest is not transactional, and doesn’t automatically rollback. This is intentional – it means that I’m testing the transactional semantics of the code. This still counts as a unit test, though, because it’s an in-memory database – deleting all the data is no slower than rolling back the transaction. The JBehave test will need to be able to do the same thing)

Now that we have a working service, it’s time to move on to the JBehave work. Let’s start with the story.

When we create a Foo called 'bar'
Then it gets saved in the database with the name 'bar'

And the Story and Steps:

</pre>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/testContext.xml")
public class FooServiceStory extends JUnitStory {
    @Autowired private ApplicationContext context;

    @Autowired private JdbcTemplate jdbc;

    @After public void cleanData() {
        jdbc.execute("truncate schema PUBLIC and commit");
    }

    @Override public Configuration configuration() {
        return new MostUsefulConfiguration();
    }

    @Override public List<CandidateSteps> candidateSteps() {
        return new SpringStepsFactory(configuration(), context).createCandidateSteps();
    }
}
@Component
public class FooServiceSteps {
    @Autowired private FooService test;
    @Autowired private JdbcTemplate jdbc;

    @When("we create a Foo called 'bar'")
    public void createFoo() {
        test.createFoo("foo", "this is a test foo");
    }

    @Then("it gets saved in the database with the name 'bar'")
    public void lookForFoo() {
        assertEquals("we end with one foo", 1, jdbc.queryForInt("select count(*) from foo"));
    }
}

Again, this is kind of brain-dead simple, but it works. The feedback from running the test inside the IDE is pretty poor, but I can make the test pass or fail by changing the assertion. So, at this point, I’ve got a Spring-enabled JBehave test.

One part that should be explained is the candidateSteps() method. This is the method used by the JUnitStory super-class to find the step classes. The SpringStepsFactory is a JBehave class that knows how to use a Spring ApplicationContent – it looks through all the beans defined in the context to see if they have JBehave annotations on them.

That’s where I’m leaving it for now. In the next instalment, I want to make this be based off JBehave’s own infrastructure for Spring, as opposed to leveraging the JUnit stuff. It’s my sincere hope that going that way I can improve the in-IDE experience, as well as improve the reporting. I’m a long way from being happy with this right now.

Update: I’ve updated the example to use the SpringStepsFactory class to create the step. This is a better approach – especially if the test shown above was a base class, or if it extended from the JUnitStories class instead.

About these ads

3 thoughts on “AiL – JBehave and Spring

  1. Brian Repko

    You should look at the JBehave example on Spring Security – shows how to test Spring-based services (in this case Spring Security AuthenticationManager authenticate method) with JBehave.

    Reply
    1. Robert Watkins Post author

      Thanks, Brian. My research is running ahead of my blog posts – I have looked at those, and my one of my next posts in this series will be using a similar technique (in particular, using the SpringStepsFactory demonstrated there). My next post, though, is going to look at the SpringAnnotatedEmbedderRunner (though I may yet decide to reverse that order… ;)

      For those playing along at home, the examples can be found at the JBehave Github account

      Reply
    2. Robert Watkins Post author

      I’ve updated my example to use the SpringStepsFactory, as per the Spring Security example – it is a better approach, and I would probably have got there on the first draft if I didn’t post at 11pm at night. ;)

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s