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. 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.

    • 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

    • 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. ;)

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 )

Connecting to %s