Showing posts with label bdd. Show all posts
Showing posts with label bdd. Show all posts

Wednesday, July 8, 2015

BDD with groovy and Spock

Groovy language is not as "strict" as Java, I don't think it does not makes a sense to create using Groovy complex production applications, because we can have situation when everything is compiling, but not working. It can we very hard to understand where exactly variable type User was used like it has type Task(for example)  :)   But for writing test, groovy - is a very good option, because it can make writing of test much easier, with writing less code.  In this post I'll show how can we test Java code by BDD methodology, using groovy language and spock library. 

Wiki: 

Example how it looks :
def "it should say Hi for regular name"() {
    given:
    def person=new TestJavaClass()

    when :
    def result=person.sayHi("Huan Sebastyan")

    then:
    result!=null    result=="Hi, Huan Sebastyan"}


1. Project structure 

We have 2 Java classes for testing in our project: JavaTestClass.java, AnotherJavaClass.java, and one groovy test file : GroovyTest.groovy. 



2. Main project file(pom.xml)

We have to include some spock-related dependencies into pom file. I commented dependencies which was not used in this project, but can be used in future.


<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.demien</groupId>
  <artifactId>spock</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>Test Spock Project</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
  </properties>

  <build>
    <plugins>
      <!-- Mandatory plugins for using Spock -->
      <plugin>
        <!-- The gmavenplus plugin is used to compile Groovy code. To learn more about this plugin, 
        visit https://github.com/groovy/GMavenPlus/wiki -->
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>1.4</version>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
              <goal>testCompile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <!-- Optional plugins for using Spock -->
      <!-- Only required if names of spec classes don't match default Surefire patterns (`*Test` etc.) -->
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <useFile>false</useFile>
          <includes>
            <include>**/*Spec.java</include>
          </includes>
        </configuration>
      </plugin>
      <!-- Only required for spock-example build -->
      <plugin>
        <artifactId>maven-deploy-plugin</artifactId>
        <version>2.5</version>
        <configuration>
          <skip>true</skip>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <!-- Mandatory dependencies for using Spock -->
    <dependency>
      <groupId>org.spockframework</groupId>
      <artifactId>spock-core</artifactId>
      <version>1.0-groovy-2.4</version>
      <scope>test</scope>
    </dependency>
    <!-- Optional dependencies for using Spock -->
    <dependency> <!-- use a specific Groovy version rather than the one specified by spock-core -->
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>2.4.1</version>
    </dependency>
  <!-- enables mocking of classes (in addition to interfaces) -->
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib-nodep</artifactId>
      <version>3.1</version>
      <scope>test</scope>
    </dependency>

  <!-- enables mocking of classes without default constructor (together with CGLIB)
    <dependency>
      <groupId>org.objenesis</groupId>
      <artifactId>objenesis</artifactId>
      <version>2.1</version>
      <scope>test</scope>
    </dependency>
    -->
  <!-- only required if Hamcrest matchers are used
    <dependency>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest-core</artifactId>
      <version>1.3</version>
      <scope>test</scope>
    </dependency>
    -->
    <!-- Dependencies used by examples in this project (not required for using Spock)
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.4.185</version>
    </dependency>
    -->
  </dependencies>


  <!-- Only required if a snapshot version of Spock is used
  <repositories>

    <repository>
      <id>spock-snapshots</id>
      <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
  </repositories>
  -->

  <!-- Only required in spock-example build
  <distributionManagement>
    <repository>
      <id>foo</id>
      <url>file:///fake.repository.to.make.maven.happy</url>
    </repository>
    <snapshotRepository>
      <id>bar</id>
      <url>file:///fake.repository.to.make.maven.happy</url>
    </snapshotRepository>
  </distributionManagement>
  -->
</project>

3. JavaTestClass

It's a very simple class, it just has 2 methods : sayHi and getHistory(returns List with history of invocatons). 


package com.demien.spock;

import java.util.ArrayList;
import java.util.List;

public class TestJavaClass {

    private List<String> history=new ArrayList<String>();

    public void checkName(String name) {
        if (name==null) {
            throw new IllegalArgumentException("name is null!");
        }
    }

    public String sayHi(String name) {
        checkName(name);
        history.add(name);
        return "Hi, "+name;
    }

    public List<String> getHistoryItems() {
        return history;
    }
}


4.AnotherJavaClass

Just another simple class which use JavaTestClass for method intruduceYourself. Also it use getHistory method for transforming result from JavaTestClass to String(from List). 


package com.demien.spock;

public class AnotherJavaClass {
    TestJavaClass testJavaClass;

    public void setTestJavaClass(TestJavaClass testJavaClass) {
        this.testJavaClass = testJavaClass;
    }

    public String introduceYourself() {
        return testJavaClass.sayHi("I'm AnotherJavaClass");
    }

    public String getHistory() {
        StringBuilder result=new StringBuilder();
        for (String s:testJavaClass.getHistoryItems()) {
            if (result.length()>0) {
                result.append(",");
            }
            result.append(s);
        }
        return result.toString();
    }
}

5. Groovy test

By comments in code I tried to explain everything what is going on. I believe, it's easy to understand.


package com.demien.spock

import spock.lang.Specification;

class GroovyTest extends Specification {

    def "it should say Hi for regular name"() {
        given:
        def person=new TestJavaClass()

        when :
        def result=person.sayHi("Huan Sebastyan")

        then:
        result!=null
        result=="Hi, Huan Sebastyan"
    }

    def "it should thrown an error if name is null"() {
        given:
        def person=new TestJavaClass()

        when :
        def result=person.sayHi(null)

        then:
        thrown(IllegalArgumentException)
    }

    // mock - is a "empty" class: all methods are returning null.
    def "check method invocation count"() {
        given:
        TestJavaClass mock=Mock()
        AnotherJavaClass anotherJavaClass=new AnotherJavaClass(testJavaClass: mock)

        when:
        mock.sayHi("Test Name") // first invocation
        anotherJavaClass.introduceYourself() // second invocation

        then:
        2*mock.sayHi(_)
    }

    //  you have to re-define each method you want to use for mock
    def "Mocked class used in another class should return mocked value"() {
        setup :
        TestJavaClass mock=Mock()
        mock.sayHi(_)>>"EMPTY"
        AnotherJavaClass anotherJavaClass=new AnotherJavaClass(testJavaClass: mock)

        when:
        String result=anotherJavaClass.introduceYourself()

        then:
        result=="EMPTY"
    }

    def "Mocked class should return proper mocked history"() {
        setup :
        TestJavaClass mock=Mock()
        mock.getHistoryItems()>>["one", "two", "three"]
        AnotherJavaClass anotherJavaClass=new AnotherJavaClass(testJavaClass: mock)

        when:
        String result=anotherJavaClass.getHistory()

        then:
        result=="one,two,three"
    }

    // stubbed class - "empty" class like mock, but methods are not returning values at all
    // so, like in mocks, you have to re-define each method you want to use
    def "stubbed class used in another class"() {
        setup:
        TestJavaClass stub=Stub()

        stub.sayHi(_)>>{String name->
            "Hello, "+name
        }
        AnotherJavaClass anotherJavaClass=new AnotherJavaClass(testJavaClass: stub)

        when:
        String result=anotherJavaClass.introduceYourself()

        then:
        result=="Hello, I'm AnotherJavaClass"
    }

    // spy - is a "wrapper" - 100% working copy of class
    //  but you can re-define methods if you want
    def "spy test"() {
        setup:
        TestJavaClass spy=Spy()
        spy.checkName(null)>>{} // now calling this method with (null) will not cause exeption

        AnotherJavaClass anotherJavaClass=new AnotherJavaClass(testJavaClass: spy)

        when:
        String resultFromClass=anotherJavaClass.introduceYourself()
        String resultFromSpy=spy.sayHi(null)


        then:
        resultFromClass=="Hi, I'm AnotherJavaClass"
        resultFromSpy=="Hi, null" // exception was not thrown
    }

}

6. Conclusion.

I think groovy is becoming more and more popular for writing test, and spock framework will help it with that! Source code can be downloaded from here.




Saturday, February 14, 2015

JBehave - getting started

First of all - what is JBehave ? About that, it's better to read from it original site : http://jbehave.org/ : 

JBehave is a framework for Behaviour-Driven Development (BDD). BDD is an evolution of test-driven development (TDD) and acceptance-test driven design, and is intended to make these practices more accessible and intuitive to newcomers and experts alike. It shifts the vocabulary from being test-based to behaviour-based, and positions itself as a design philosophy. 

In shorts, it's addon for JUnit,which is giving possibilities to make testing process more transparent to business(non-developer) users. For example, with JBehave we can write test descriptions in plain text (.story) files. 

0. Goal. 

As a developer , I want to test my ActiveMQ application using BDD methodology.
Component of my application:
Active MQ getting started -1: Producer/Consumer(Sender/Receiver) 



So, I want to re-write my JUnit tests using JBehave.

My test cases :
1. Producer/Consumer : simple test, 1 message have to be received by 1 Consumer.
2. Producer/Consumer : multiple test, with several consumers of one queue, 1 message have to be received by only 1 Consumer.
3. Publisher/Subscriber : all subscribers of topic have to receive the message. 

1. Stories

What is "story"?
From jbehave.com:
Behaviour-Driven Development encourages you to start defining the stories via scenarios that express the desired behaviour in a textual format, e.g.:
Given a stock of symbol STK1 and a threshold of 10.0
When the stock is traded at 5.0
Then the alert status should be OFF
The textual scenario should use the language of the business domain and shield away as much as possible the details of the technical implementation. Also, it should be given a name that is expressive of the functionality that is being verified, i.e. trader_is_alerted_of_status.story.

So,let's re-write our test cases from above,to "stories" syntax.
For that I created 2 files in test/resource directory: ProducerConsumer.story and PublisherSubscriber.story. In these files, I have to re-formulate test cases,using BDD syntax(Scenario, Give, When, Then).

My test stories files: 

ProducerConsumer.story : 
Scenario: simple message receiving by one consumer
Given one producer, one consumer, one message
When producer sends message to queue
Then consumer receives message from queue

Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message
When producer sends message to queue
Then only one consumer have to receive message from queue

PublisherSubscriber.story: 
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message
When publisher sends message
Then all subscribers have to receive this message

2. Test classes

Now we need JUnit tests which have to cover our stories.  I created 2 files (each for each story file) : PublisherSubscriberJB and ProducesConsumerJB. They are empty now, we will implement them later.

ProducesConsumerJB:

package com.demien.amq.jbehave;

/**
 * Created by dmitry on 14.02.15.
 */
public class ProducerConsumerJB {
}


PublisherSubscriberJB:

package com.demien.amq.jbehave;

/**
 * Created by dmitry on 09.02.15.
 */
public class PublisherSubscriberJB {


}


3. JBehave runner.

As I mentioned before, JBehave  - addon on JUnit. So, we have to create jbehave-runner file,which will make our JUnit tests consider our stories files.
I copy/pasted it from one of examples from jbehave site.

package com.demien.amq.jbehave;

import org.jbehave.core.Embeddable;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.i18n.LocalizedKeywords;
import org.jbehave.core.io.LoadFromClasspath;
import org.jbehave.core.io.StoryFinder;
import org.jbehave.core.junit.JUnitStories;
import org.jbehave.core.model.ExamplesTableFactory;
import org.jbehave.core.parsers.RegexStoryParser;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.jbehave.core.steps.ParameterConverters;

import java.text.SimpleDateFormat;
import java.util.List;

import static org.jbehave.core.io.CodeLocations.codeLocationFromClass;
import static org.jbehave.core.reporters.Format.CONSOLE;
import static org.jbehave.core.reporters.Format.HTML;
import static org.jbehave.core.reporters.Format.TXT;
import static org.jbehave.core.reporters.Format.XML;

/**
 * Created by dmitry on 09.02.15.
 */
public class JBehaveRunner extends JUnitStories {

        public JBehaveRunner() {
            configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(true)
                    .doIgnoreFailureInView(true).useThreads(1).useStoryTimeoutInSecs(60);
        }

        @Override
        public Configuration configuration() {
            Class<? extends Embeddable> embeddableClass = this.getClass();
            // Start from default ParameterConverters instance
            ParameterConverters parameterConverters = new ParameterConverters();
            // factory to allow parameter conversion and loading from external resources (used by StoryParser too)
            ExamplesTableFactory examplesTableFactory = new ExamplesTableFactory(new LocalizedKeywords(), new LoadFromClasspath(embeddableClass), parameterConverters);
            // add custom converters
            parameterConverters.addConverters(new ParameterConverters.DateConverter(new SimpleDateFormat("yyyy-MM-dd")),
                    new ParameterConverters.ExamplesTableConverter(examplesTableFactory));
            return new MostUsefulConfiguration()
                    .useStoryLoader(new LoadFromClasspath(embeddableClass))
                    .useStoryParser(new RegexStoryParser(examplesTableFactory))
                    .useStoryReporterBuilder(new StoryReporterBuilder()
                            .withCodeLocation(codeLocationFromClass(embeddableClass))
                            .withDefaultFormats()
                            .withFormats(CONSOLE, TXT, HTML, XML))
                    .useParameterConverters(parameterConverters);
        }

        @Override
        public InjectableStepsFactory stepsFactory() {
            return new InstanceStepsFactory(configuration(), new PublisherSubscriberJB(), new ProducerConsumerJB());
        }

        @Override
        protected List<String> storyPaths() {
            return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), "*.story", "*excluded*.story");

        }
}

Most interesting thing here is function stepsFactory - here we have to list our "steps"  - JUnit tests which have to cover our stories, which we created on previous steps.


4. First run

Now we can run our JBehave runner(just as regular JUnit test) to see if everything is fine: we have to be sure that JBehave have found our .story files.
My output after run:

Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=true,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=60,failOnStoryTimeout=false,threads=1]

(BeforeStories)

Running story ProducerConsumer.story

(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
Given one producer, one consumer, one message (PENDING)
When producer sends message to queue (PENDING)
Then consumer receives message from queue (PENDING)
@Given("one producer, one consumer, one message")
@Pending
public void givenOneProducerOneConsumerOneMessage() {
  // PENDING
}

@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
  // PENDING
}

@Then("consumer receives message from queue")
@Pending
public void thenConsumerReceivesMessageFromQueue() {
  // PENDING
}


Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message (PENDING)
When producer sends message to queue (PENDING)
Then only one consumer have to receive message from queue (PENDING)
@Given("one producer, several consumers, one message")
@Pending
public void givenOneProducerSeveralConsumersOneMessage() {
  // PENDING
}

@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
  // PENDING
}

@Then("only one consumer have to receive message from queue")
@Pending
public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() {
  // PENDING
}



Running story PublisherSubscriber.story

(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message (PENDING)
When publisher sends message (PENDING)
Then all subscribers have to receive this message (PENDING)
@Given("one publisher, several subscribers, one message")
@Pending
public void givenOnePublisherSeveralSubscribersOneMessage() {
  // PENDING
}

@When("publisher sends message")
@Pending
public void whenPublisherSendsMessage() {

Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=true,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=60,failOnStoryTimeout=false,threads=1]

(BeforeStories)

Running story ProducerConsumer.story

(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
Given one producer, one consumer, one message (PENDING)
When producer sends message to queue (PENDING)
Then consumer receives message from queue (PENDING)
@Given("one producer, one consumer, one message")
@Pending
public void givenOneProducerOneConsumerOneMessage() {
  // PENDING
}

@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
  // PENDING
}

@Then("consumer receives message from queue")
@Pending
public void thenConsumerReceivesMessageFromQueue() {
  // PENDING
}


Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message (PENDING)
When producer sends message to queue (PENDING)
Then only one consumer have to receive message from queue (PENDING)
@Given("one producer, several consumers, one message")
@Pending
public void givenOneProducerSeveralConsumersOneMessage() {
  // PENDING
}

@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
  // PENDING
}

@Then("only one consumer have to receive message from queue")
@Pending
public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() {
  // PENDING
}



Running story PublisherSubscriber.story

(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message (PENDING)
When publisher sends message (PENDING)
Then all subscribers have to receive this message (PENDING)
@Given("one publisher, several subscribers, one message")
@Pending
public void givenOnePublisherSeveralSubscribersOneMessage() {
  // PENDING
}

@When("publisher sends message")
@Pending
public void whenPublisherSendsMessage() {
  // PENDING
}

@Then("all subscribers have to receive this message")
@Pending
public void thenAllSubscribersHaveToReceiveThisMessage() {
  // PENDING
}


(AfterStories)  // PENDING
}

@Then("all subscribers have to receive this message")
@Pending
public void thenAllSubscribersHaveToReceiveThisMessage() {
  // PENDING
}


(AfterStories)


 Everything looks good: jbehave found both .story files and even generated for us "mockup"(function definitions) of future implementation!

So, we can copy/paste function definitions to our  test classes in to"fill"(implement) them.

5. Stories implementation.

Now, let's put code into generated function definitions.
 
ProducerConsumerJB

package com.demien.amq.jbehave;

import com.demien.amq.Consumer;
import com.demien.amq.Producer;
import com.demien.amq.TestObject;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;

/**
 * Created by dmitry on 14.02.15.
 */
public class ProducerConsumerJB {

    public static String brokerURL = "tcp://localhost:61616";
    private final ConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL);
    private final String queueName1="TestQueue1";
    private final String queueName2="TestQueue2";

    Producer<TestObject> producer;
    Consumer<TestObject> consumer;
    List<Consumer<TestObject>> consumers;
/*
    Scenario: simple message receiving by one consumer
    Given one producer, one consumer, one message (PENDING)
    When producer sends message to queue (PENDING)
    Then consumer receives message from queue (PENDING)
*/
    @Given("one producer, one consumer, one message")
    public void givenOneProducerOneConsumerOneMessage() throws JMSException {
        producer=new Producer<TestObject>(factory, queueName1);
        consumer=new Consumer<TestObject>(factory, queueName1);
        consumer.setConsumerId("THE_ONLY_CONSUMER");
    }

    @When("producer sends message to queue")
    public void whenProducerSendsMessageToQueue() throws JMSException, InterruptedException {
        producer.postObjectMessage(new TestObject());
        Thread.sleep(1000);
    }

    @Then("consumer receives message from queue")
    public void thenConsumerReceivesMessageFromQueue() {
        int receivedMessageCount=consumer.getMessages().size();
        assertEquals(1, receivedMessageCount);
    }

/*
    Scenario: simple message receiving by several consumers:only one of them have to receive message
    Given one producer, several consumers, one message (PENDING)
    When producer sends message to queue (PENDING)
    Then only one consumer have to receive message from queue (PENDING)
*/
    @Given("one producer, several consumers, one message")
    public void givenOneProducerSeveralConsumersOneMessage() throws JMSException {
        producer=new Producer<TestObject>(factory, queueName2);
        consumers=new ArrayList<Consumer<TestObject>>();
        for (int i=0;i<10;i++) {
            Consumer<TestObject> eachConsumer=new Consumer<TestObject>(factory, queueName2);
            eachConsumer.setConsumerId("Consumer#"+Integer.toString(i));
            consumers.add(eachConsumer);
        }
    }
/* - already implemented
    @When("producer sends message to queue")
    public void whenProducerSendsMessageToQueue() {
        // PENDING
    }
*/
    @Then("only one consumer have to receive message from queue")
    public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() {
        int receivedMessageCount=0;
        for (Consumer<TestObject> eachConsumer: consumers) {
            receivedMessageCount=receivedMessageCount+eachConsumer.getMessages().size();
        }
        assertEquals(1, receivedMessageCount);
    }
} 
 
 
PublisherSubscriberJB

package com.demien.amq.jbehave;

import com.demien.amq.Publisher;
import com.demien.amq.Subscriber;
import com.demien.amq.TestObject;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertTrue;

/**
 * Created by dmitry on 09.02.15.
 */
public class PublisherSubscriberJB {
    public static String brokerURL = "tcp://localhost:61616";
    private final ConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL);
    private final String topicName="TestTopic";

    private final int SUBSCRIBERS_COUNT=10;
    Long TEST_ID=-1L;
    String TEST_NAME="test name";

    Publisher<TestObject> publisher;
    List<Subscriber<TestObject>> subscribers;

/*    (PublisherSubscriber.story)
    Scenario: broadcast message receiving by all subscribers of topic
    Given one publisher, several subscribers, one message (PENDING)
    When publisher sends message (PENDING)
    Then all subscribers have to receive this message (PENDING)
*/
    @Given("one publisher, several subscribers, one message")
    public void givenOnePublisherSeveralSubscribersOneMessage() throws JMSException {
        publisher=new Publisher<TestObject>(factory, topicName);

        subscribers=new ArrayList<Subscriber<TestObject>>();
        for (int i=0; i<SUBSCRIBERS_COUNT; i++) {
            Subscriber<TestObject> subscriber=new Subscriber<TestObject>(factory, topicName);
            subscriber.setSubscriberId(Integer.toString(i));
            subscribers.add(subscriber);
        }
    }

    @When("publisher sends message")
    public void whenPublisherSendsMessage() throws JMSException, InterruptedException {

        TestObject testObject=new TestObject();
        testObject.id=new Long(TEST_ID);
        testObject.name=new String(TEST_NAME);

        //post message
        publisher.postObjectMessage(testObject);
        Thread.sleep(1000);
    }

    @Then("all subscribers have to receive this message")
    public void thenAllSubscribersHaveToReceiveThisMessage() {
        for (Subscriber<TestObject> subscriber:subscribers) {
            TestObject received=subscriber.getMessages().get(0);
            assertTrue(received.name.equals(TEST_NAME));
            assertTrue(received.id.equals(TEST_ID));
        }
    }

}


6. Final run and results

Now, we can run our message broker and after the we can finally run our JBehave tests .
My results :

Running story ProducerConsumer.story

(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
log4j:WARN No appenders could be found for logger (org.apache.activemq.transport.WireFormatNegotiator).
log4j:WARN Please initialize the log4j system properly.
Given one producer, one consumer, one message
Sending message:com.demien.amq.TestObject@807bbc
Consumer[THE_ONLY_CONSUMER] Message received:
When producer sends message to queue
Then consumer receives message from queue

Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message
Sending message:com.demien.amq.TestObject@7b0aef
Consumer[Consumer#0] Message received:
When producer sends message to queue
Then only one consumer have to receive message from queue


Running story PublisherSubscriber.story

(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message
Subscriber[0] received message.
Subscriber[3] received message.
Subscriber[4] received message.
Subscriber[1] received message.
Subscriber[2] received message.
Subscriber[7] received message.
Subscriber[6] received message.
Subscriber[9] received message.
Subscriber[5] received message.
Subscriber[8] received message.
When publisher sends message
Then all subscribers have to receive this message

As we can see, result are very easy for understanding even for users which are not related with development. Also Jbehave can generate very beautiful html tables with results (whey are located in /target/jbehave directory) such as :
 

Story Reports

StoriesScenariosGivenStory ScenariosSteps

NameExcludedTotalSuccessfulPendingFailedExcludedTotalSuccessfulPendingFailedExcludedTotalSuccessfulPendingFailedNot PerformedIgnorableDuration (hh:mm:ss.SSS)View
AfterStories0000000000000000000:00:00.000stats|html|xml |txt
BeforeStories0000000000000000000:00:00.000stats|xml|html |txt
ProducerConsumer0220000000066000000:00:03.000stats|html|xml |txt
PublisherSubscriber0110000000033000000:00:01.000stats|xml|html |txt
40330000000099000000:00:04.000Totals

Full source code could be downloaded from here.