Mostrando entradas con la etiqueta junit testing java. Mostrar todas las entradas
Mostrando entradas con la etiqueta junit testing java. Mostrar todas las entradas

martes, septiembre 19, 2017

Testing code that uses Java System Properties

Sometimes your code uses any Java System Property to configure itself. Usually these classes are configuration classes that can get properties from different sources and one of valid one is using Java System Properties.

The problem is how to write tests for this code? Obviously to maintain your tests isolated you need to set and unset them for each test, restoring old value if for example you are dealing with a global property which is already set before executing tests, and of course in case of an error do not forget to unset/restore the value. So arrived at this point the test might look like:

Notice that this structure should be repeated for each test method that requires an specific system property, so this structure becomes a boilerplate code.

To avoid having to repeat this code over and over again, you can use System Rules project which is a collection of JUnit rules for testing code that uses java.lang.System 

The first thing you need to do is add System Rules dependency as test scope in your build tool, which in this case is com.github.stefanbirkner:system-rules:1.16.0.

Then you need to register the JUnit Rule into your test class.

In this case, you can freely set a System property in your test, the JUnit rule will take care of saving and restoring the System property.

That's it, really easy, no boilerplate code and help you maintaining your tests clean.

Just one notice, these kind of tests are not thread safe, so you need to be really cautious when you use for example surefire plugin with forks. One possible way to avoiding this is by using net.jcip.annotations.NotThreadSafe.class capabilities.

We keep learning,
Alex

Polly wants a cracker, I think I should get off her first, I think she wants some water, To put out the blow torch (Polly - Nirvana)



martes, marzo 19, 2013

Testing Spring Data Neo4j Applications with NoSQLUnit

Spring Data Neo4j


Spring Data Neo4j is the project within Spring Data project which provides an extension to the Spring programming model for writing applications that uses Neo4j as graph database.
To write tests using NoSQLUnit for Spring Data Neo4j applications, you do need nothing special apart from considering that Spring Data Neo4j uses a special property called type in graph nodes and relationships which stores the fully qualified classname of that entity.

Apart from type property at node/relationship level, we also need to create one index for nodes and one index for relationships. In case of nodes, types index name is required, meanwhile rel_types is required for relationships. In both cases we must set key value to className and value to full qualified classname.

Note Type mapping
IndexingNodeTypeRepresentationStrategy and IndexingRelationshipTypeRepresentationStrategy are used as default type mapping implementation, but you can also use SubReferenceNodeTypeRepresentationStrategy which stores entity types in a tree in the graph representing the type and interface hierarchy, or you can customize even more by implementing NodeTypeRepresentationStrategy interface.

Hands on Work

Application

Starfleet has asked us to develop an application for storing all starfleet members, with their relationship with other starfleet members, and the ship where they serve.

The best way to implement this requirement is using Neo4j database as backend system. Moreover Spring Data Neo4j is used at persistence layer.

This application is modelized into two Java classes, one for members and another one for starships. Note that for this example there are no properties in relationships, so only nodes are modelized.

Member class

@NodeEntity
public class Member {

        private static final String COMMANDS = "COMMANDS";

        @GraphId Long nodeId;

        private String name;

        private Starship assignedStarship;

        public Member() {
                super();
        }

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

        @Fetch @RelatedTo(type=COMMANDS, direction=Direction.OUTGOING)
        private Set<Member> commands;

        public void command(Member member) {
                this.commands.add(member);
        }

        public Set<Member> commands() {
                return this.commands;
        }

        public Starship getAssignedStarship() {
                return assignedStarship;
        }

        public String getName() {
                return name;
        }

        public void assignedIn(Starship starship) {
                this.assignedStarship = starship;
        }

        //Equals and Hash methods
}
Starship class

@NodeEntity
public class Starship {

        private static final String ASSIGNED = "assignedStarship";

        @GraphId Long nodeId;

        private String starship;

        public Starship() {
                super();
        }

        public Starship(String starship) {
                this.starship = starship;
        }

        @RelatedTo(type = ASSIGNED, direction=Direction.INCOMING)
        private Set<Member> crew;

        public String getStarship() {
                return starship;
        }

        public void setStarship(String starship) {
                this.starship = starship;
        }

        //Equals and Hash methods
}

Apart from model classes, we also need two repositories for implementing CRUD operations, and spring context xml file. Spring Data Neo4j uses Spring Data Commons infrastructure allowing us to create interface based compositions of repositories, providing default implementations for certain operations.

MemberRepository class

public interface MemberRepository extends GraphRepository<Member>,
                RelationshipOperationsRepository<Member> {

        Member findByName(String name);

}

See that apart from operations provided by GrapRepository interface like save, findAll, findById, … we are defining one query method too called findByName. Spring Data Neo4j repositories (and most of Spring Data projects) provide a mechanism to define queries using the known Ruby on Rails approach for defining finder queries.

StarshipRepository class

public interface StarshipRepository extends GraphRepository<Starship>,
                RelationshipOperationsRepository<Starship> {
}
application-context file

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/data/neo4j
           http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">

     <context:component-scan base-package="com.lordofthejars.nosqlunit.springdata.neo4j"/>
     <context:annotation-config/>

     <neo4j:repositories base-package="com.lordofthejars.nosqlunit.springdata.repository"/>

</beans>

Testing

Unit Testing

As it has been told previously, for writing datasets for Spring Data Neo4j, we don’t have to do anything special beyond creating node and relationship properties correctly and defining the required indexes. Let’s see the dataset used to test the findByName method by seeding Neo4j database.

star-trek-TNG-dataset.xml file

<?xml version="1.0" ?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
     <key id="name" for="node" attr.name="name" attr.type="string"></key>
     <key id="__type__" for="node" attr.name="__type__" attr.type="string"></key>
     <key id="starship" for="node" attr.name="starship" attr.type="string"></key>
     <graph id="G" edgedefault="directed">

       <node id="3">
        <data key="__type__">com.lordofthejars.nosqlunit.springdata.neo4j.Member</data>
        <data key="name">Jean-Luc Picard</data>
        <index name="__types__" key="className">com.lordofthejars.nosqlunit.springdata.neo4j.Member</index>
      </node>

      <node id="1">
        <data key="__type__">com.lordofthejars.nosqlunit.springdata.neo4j.Member</data>
        <data key="name">William Riker</data>
        <index name="__types__" key="className">com.lordofthejars.nosqlunit.springdata.neo4j.Member</index>
      </node>

      <node id="4">
        <data key="__type__">com.lordofthejars.nosqlunit.springdata.neo4j.Starship</data>
        <data key="starship">NCC-1701-E</data>
        <index name="__types__" key="className">com.lordofthejars.nosqlunit.springdata.neo4j.Starship</index>
      </node>

      <edge id="11" source="3" target="4" label="assignedStarship"></edge>
      <edge id="12" source="1" target="4" label="assignedStarship"></edge>
      <edge id="13" source="3" target="1" label="COMMANDS"></edge>

    </graph>
</graphml>

See that each node has at least one type property with full qualified classname and an index with name types, key className and full qualified classname as value.
Next step is configuring application context for unit tests.

application-context-embedded-neo4j.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/data/neo4j
           http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">


        <import resource="classpath:com/lordofthejars/nosqlunit/springdata/neo4j/application-context.xml"/>
        <neo4j:config storeDirectory="target/config-test"/>

</beans>
Notice that we are using Neo4j namespace for instantiating an embedded Neo4j database.
And now we can write the JUnit test case:

WhenInformationAboutAMemberIsRequired

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("application-context-embedded-neo4j.xml")
public class WhenInformationAboutAMemberIsRequired {

        @Autowired
        private MemberRepository memberRepository;
        @Autowired
        private StarshipRepository starshipRepository;

        @Autowired
        private ApplicationContext applicationContext;

        @Rule
        public Neo4jRule neo4jRule = newNeo4jRule()
                        .defaultSpringGraphDatabaseServiceNeo4j();

        @Test
        @UsingDataSet(locations = "star-trek-TNG-dataset.xml", loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
        public void information_about_starship_where_serves_and_members_under_his_service_should_be_retrieved()  {

                Member jeanLuc = memberRepository.findByName("Jean-Luc Picard");

                assertThat(jeanLuc, is(createMember("Jean-Luc Picard")));
                assertThat(jeanLuc.commands(), containsInAnyOrder(createMember("William Riker")));

                Starship starship = starshipRepository.findOne(jeanLuc.getAssignedStarship().nodeId);
                assertThat(starship, is(createStarship("NCC-1701-E")));
        }

        private Object createStarship(String starship) {
                return new Starship(starship);
        }

        private static Member createMember(String memberName) {
                return new Member(memberName);
        }
}

There are some important points in the previous class to take under consideration:
  1. Recall that we need to use Spring ApplicationContext object to retrieve embedded Neo4j instance defined into Spring application context.
  2. Since lifecycle of database is managed by Spring Data container, there is no need to define any NoSQLUnit lifecycle manager.

Integration Test

Unit tests are usually run against embedded in-memory instances, but in production environment you may require access to external Neo4j servers by using Rest connection, or in case of Spring Data Neo4j instantiating SpringRestGraphDatabase class. You need to write tests to validate that your application still works when you integrate your code with a remote server, and this tests are typically known as integration tests.
To write integration tests for our application is as easy as defining an application context with SpringRestGraphDatabase and allow NoSQLUnit to control the lifecycle of Neo4j database.

.application-context-managed-neo4j.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/data/neo4j
           http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">


        <import resource="classpath:com/lordofthejars/nosqlunit/springdata/neo4j/application-context.xml"/>

        <bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
                <constructor-arg index="0" value="http://localhost:7474/db/data"></constructor-arg>
        </bean>
        <neo4j:config graphDatabaseService="graphDatabaseService"/>

</beans>

Note how instead of registering an embedded instance, we are configuring SpringRestGraphDatabase class to connect to localhost server. And let’s implement an integration test which verifies that all starships can be retrieved from Neo4j server.

WhenInformationAboutAMemberIsRequired

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("application-context-managed-neo4j.xml")
public class WhenInformationAboutStarshipsAreRequired {

        @ClassRule
        public static ManagedNeoServer managedNeoServer = newManagedNeo4jServerRule()
                        .neo4jPath(
                                        "/Users/alexsotobueno/Applications/neo4j-community-1.7.2")
                        .build();

        @Autowired
        private StarshipRepository starshipRepository;

        @Autowired
        private ApplicationContext applicationContext;

        @Rule
        public Neo4jRule neo4jRule = newNeo4jRule()
                        .defaultSpringGraphDatabaseServiceNeo4j();

        @Test
        @UsingDataSet(locations = "star-trek-TNG-dataset.xml", loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
        public void information_about_starship_where_serves_and_members_under_his_service_should_be_retrieved() {

                EndResult<Starship> allStarship = starshipRepository.findAll();

                assertThat(allStarship, containsInAnyOrder(createStarship("NCC-1701-E")));

        }

        private Object createStarship(String starship) {
                return new Starship(starship);
        }

}

Because defaultSpringGraphDatabaseServiceNeo4j method returns a GraphDatabaseService instance defined into application context, in our case it will return the defined SpringRestGraphDatabase instance.

Conclusions

There is not much difference between writing tests for none Spring Data Neo4j applications than the ones they use it. Only keep in mind to define correctly the type property and create required indexes.

Also see that from the point of view of NoSQLUnit there is no difference between writing unit or integration tests, apart of lifecycle management of the database engine.

Download Code

We keep learning,
Alex.
Gonna rise up, Burning black holes in dark memories, Gonna rise up, Turning mistakes into gold (Rise - Eddie Vedder)

Music: http://www.youtube.com/watch?v=uuVf4xiRsJQ

miércoles, marzo 06, 2013

NoSQLUnit 0.7.5 Released



NoSQLUnit is a JUnit extension to make writing unit and integration tests of systems that use NoSQL backend easier. Visit official page for more information.

In 0.7.5 release, next changes has been added:
We keep learning,
Alex.
Cuando la pena cae sobre mi, el mundo deja de existir, miro hacia atrás, y busco entre mis recuerdos (Entre Mis Recuerdos - Luz Casal)

Music: http://www.youtube.com/watch?v=zUnOWCURe2M

lunes, enero 07, 2013

NoSQLUnit 0.7.3 Released



NoSQLUnit is a JUnit extension to make writing unit and integration tests of systems that use NoSQL backend easier. Visit official page for more information.

In 0.7.3 release, next changes has been added:

  • Support for Infinispan.
  • Adding the possibility to add custom insertion and comparison methods for each engine. Thanks to Bob Tiernay for the idea. https://github.com/lordofthejars/nosql-unit/issues/45
  • Adding the possibility to avoid NoSQLUnit injects fields annotated by @Inject by using @ByContainer annotation.  Very useful for Spring Framework Tests, Arquillian Tests or Needle Tests.
  • Removed JMockMongo as embedded Mongo implementation for Fongo project. Users should not notice any difference from the point of view of NoSQLUnit. Thank to Bob Tiernay for providing this valuable information about Fongo.
  • Updated mongo-java-driver to 2.10.1.
  • Updated neo4j to 1.8.
  • Fixed bug #46 thanks to MrKeyholder for discovering and attaching the solution code.
We keep learning,
Alex.
Fiery mountain beneath the moon, The words unspoken, we'll be there soon, For home a song that echoes on, And all who find us will know the tune. (The Lonely Mountain - Neil Finn)

jueves, diciembre 20, 2012

NoSQLUnit 0.7.1 Released


NoSQLUnit is a JUnit extension to make writing unit and integration tests of systems that use NoSQL backend easier. Visit official page for more information.

In 0.7.1 release:
  • One new NoSQL system is supported and is CouchDB
  • JUnit version has been upgraded to 4.11. Now using @Inject does not require to pass this reference.
  • Business objects do not contain any dependency to JUnit classes. This is the first step to integration to Arquillian Framework.
  • Now we can test sharding and master/slave replication of Redis servers.
  • Bug fixing.
In next version of NoSQLUnit support for Infinispan, adding class capabilities for testing sharding and master/slave replication in MongoDB and bug fixes will be provided.

We keep learning,
Alex.

Como una sonrisa, eres tú, eres tú.
Así, así, eres tú. (Eres Tú - Mocedades)



jueves, noviembre 01, 2012

NoSQLUnit 0.6.0 Released




NoSQLUnit is a JUnit extension to make writing unit and integration tests of systems that use NoSQL backend easier. Visit official page for more information.

In 0.6.0 release, one new NoSQL system is supported and is HBase.

Apache HBase is an open-source, distributed, versioned, column-oriented store.

As all databases supported by NoSQLUnit, two set of rules are provided to write HBase tests:

First set of JUnit Rules are those responsible of managing database lifecycle; basically starting and stopping HBase instance.
  • Embedded: com.lordofthejars.nosqlunit.hbase.EmbeddedHBase
  • Managed: com.lordofthejars.nosqlunit.hbase.ManagedHBase
Depending on the kind of tests you are implementing (unit test, integration test, deployment tests, …) you will require an embedded, managed or remote approach. Note that for now I haven't implemented an In-Memory approach because there is no in-memory HBase  instance, but embedded strategy for unit tests will be the better one. 

Second set of rules are those responsible of maintaining database into known state;
  • NoSQLUnit Management: com.lordofthejars.nosqlunit.hbase.HBaseRule
And finally default dataset file format in HBase is json. Dataset in HBase is the same used by Cassandra-Unit but not all fields are supported. Only fields available in TSV HBase application can be set into dataset.

We will use a very simple example used in HBase tutorial as an example of how to write unit tests for systems that uses HBase database as backend.

First of all, dataset used to maintain HBase into known state:


and finally the test case:


Stay in touch with the project and of course I am opened to any ideas that you think that could make NoSQLUnit better.
We de ze zu bu, We de sooo a ru, Un va-a pesh a lay, Un vi-I bee (Now We Are Free - Lisa Gerrard)
Music: http://www.youtube.com/watch?v=ObGYFInWrU0

domingo, octubre 14, 2012

NoSQLUnit 0.5.0 released


NoSQLUnit is a JUnit extension to make writing unit and high-level tests of systems that use NoSQL as backend easier. Visit official page for more information.

In current release instead of supporting one new engine, I focused on implementing an embedded in-memory Redis engine based on Jedis.  Read in documentation the limitations on current implementation. And of course now NoSQLUnit also supports embedded Redis apart from Managed and Remote, you only have to register EmbeddedRedis rule to use it.
@ClassRule
public static EmbeddedRedis embeddedRedis = newEmbeddedRedisRule().build();
Moreover I have fixed some issues with Managed Cassandra lifecycle.

Also I have extended the support to embedded Neo4j engine by allowing the use of instance defined into Spring context file using spring data namespace. See next example that NoSQLUnit will populate data into instance defined in application context.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/data/neo4j
            http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd">

    <context:annotation-config/>
    <neo4j:config storeDirectory="target/config-test"/>

</beans>
And in your test you only have to define SpringEmbeddedNeo4j rule passing the application context object where Neo4j is defined.
@Autowired
private ApplicationContext applicationContext;
...
@ClassRule
SpringEmbeddedNeo4j springEmbeddedGds = newSpringEmbeddedNeo4jRule().beanFactory(applicationContext).build();
And finally in this version of NoSQLUnit, I have implemented that we can use Shard connections provided by Jedis library to populate defined data into different shards. The only thing you should do is changing configuration instance of RedisRule to ShardedRedisConfiguration. See next simple example:
@Rule
public RedisRule redisRule = new RedisRule(newShardedRedisConfiguration()
         .shard(host("127.0.0.1"), port(ManagedRedis.DEFAULT_PORT))
             .password("a")
             .timeout(1000)
             .weight(1000)
         .shard(host("127.0.0.1"), port(ManagedRedis.DEFAULT_PORT + 1))
             .password("b")
             .timeout(3000)
             .weight(3000)
         .build());

And that's all for current version.

Next release 0.6.0 will contain support for HBase. Moreover there are an open poll to vote which engine would you like to see in next releases:


Stay in touch with the project and of course I am opened to any ideas that you think that could make NoSQLUnit better.

We keep learning,
Alex.

Well, these boots are made for walking, and that's just what they'll do, One of these days these boots are gonna walk all over you. (These Boots Are Made For Walkin' - Nancy Sinatra)
Music: http://www.youtube.com/watch?v=SbyAZQ45uww

miércoles, septiembre 05, 2012

NoSQLUnit 0.4.1 Released



Yo no soy marinero, Yo no soy marinero, soy capitan, Soy capitan, soy capitan, Bamba, bamba (La Bamba - Ritchie Valens)
NoSQLUnit is a JUnit extension to make writing unit and integration tests of systems that use NoSQL backend easier. Visit official page for more information.

In 0.4.1 release, after supporting Cassandra in 0.4.0 version, one new NoSQL system is supported and is Redis.

Redis is an open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.

As all databases supported by NoSQLUnit, two set of rules are provided to write Redis tests:

First set of JUnit Rules are those responsible of managing database lifecycle; basically starting and stopping Redis instance.

  • Currently Redis does not support embedded lifecycle. For this reason I am developing an embedded in-memory Redis mock. It is based in Jedis library, and will be released in next version. Issue #22.
  • Managed: com.lordofthejars.nosqlunit.redis.ManagedRedis
Second set of rules are those responsible of maintaining database into known state;
  • NoSQLUnit Management: com.lordofthejars.nosqlunit.redis.RedisRule
And finally default dataset file format in Redis is json

We will use a very simple example used in Redis tutorial as an example of how to write unit tests for systems that uses Redis database as backend.

First of all, dataset used to maintain Redis into known state:


and finally the test case:


Next release 0.4.2 will contain fixes for issues #22, #23, #24 and #25. Moreover there are an open a poll to vote which engine would you like to see in 0.5.0 release:

Vote For Next Engine

Stay in touch with the project and of course I am opened to any ideas that you think that could make NoSQLUnit better.

Music: http://www.youtube.com/watch?v=Jp6j5HJ-Cok

jueves, julio 26, 2012

Answering with Mockito




Overwhelmed by industry, Searching for a modern day savior from another place, Inclined toward charity (The Answer - Bad Religion)

When you are writing unit tests, you must keep in mind to not have dependencies to external components. To avoid this we use mock frameworks which for me the easiest one to use is Mockito.

In this post we are going to see an "advanced" technique used in Mockito to return same argument instance on a mocked method using Answer interface.

Suppose we are writing unit tests for class which manages Person and Job classes and as operation it uses a DAO class for inserting the relationship class (M:N) between Person and Job called PersonJob.

For example class under test will look something like:


So in this case it seems obvious that you need to mock personJobDao.

Let's create the mock and record the interaction:


Yes as you can see you don't know what to return, because instance is created by class under test and in the test method you don't know which instance is created by createPersonJob method. To solve this problem, you need to use thenAnswer instead of thenReturn method:

Note that Answer interface requires you to implement answer method, which in our case simply returns the first argument (PersonJob instance) of personJobDao.create method.

Now we can write assertions in peace without worrying about returned instance.

Hope you have found this post useful.

We keep learning
Alex.

Download Code
Music: http://www.youtube.com/watch?v=S2a3q0nIsoM

martes, junio 19, 2012

NoSQLUnit 0.3.0 Released


Se você me olhar vou querer te pegar, E depois namorar curtição, Que hoje vai rolar... (Balada Boa - Gustavo Lima)


Introduction

Unit testing is a method by which the smallest testable part of an application is validated. Unit tests must follow the FIRST Rules; these are Fast, Isolated, Repeatable, Self-Validated and Timely.

It is strange to think about a JEE application without persistence layer (typical Relational databases or new NoSQL databases) so should be interesting to write unit tests of persistence layer too. When we are writing unit tests of persistence layer we should focus on to not break two main concepts of FIRST rules, the fast and the isolated ones.

Our tests will be fast if they don't access network nor filesystem, and in case of persistence systems network and filesystem are the most used resources. In case of RDBMS ( SQL ), many Java in-memory databases exist like Apache Derby , H2 or HSQLDB . These databases, as their name suggests are embedded into your program and data are stored in memory, so your tests are still fast. The problem is with NoSQL systems, because of their heterogeneity. Some systems work using Document approach (like MongoDb ), other ones Column (like Hbase ), or Graph (like Neo4J ). For this reason the in-memory mode should be provided by the vendor, there is no a generic solution.

Our tests must be isolated from themselves. It is not acceptable that one test method modifies the result of another test method. In case of persistence tests this scenario occurs when previous test method insert an entry to database and next test method execution finds the change. So before execution of each test, database should be found in a known state. Note that if your test found database in a known state, test will be repeatable, if test assertion depends on previous test execution, each execution will be unique. For homogeneous systems like RDBMS , DBUnit exists to maintain database in a known state before each execution. But there is no like DBUnit framework for heterogeneous NoSQL systems.

NoSQLUnit resolves this problem by providing a JUnit extension which helps us to manage lifecycle of NoSQL systems and also take care of maintaining databases into known state.



NoSQLUnit

NoSQLUnit is a JUnit extension to make writing unit and integration tests of systems that use NoSQL backend easier and is composed by two sets of Rules and a group of annotations.

First set of Rules are those responsible of managing database lifecycle; there are two for each supported backend.

  • The first one (in case it is possible) it is the in-memory mode. This mode takes care of starting and stopping database system in "in-memory" mode. This mode will be typically used during unit testing execution.

  • The second one is the managed mode. This mode is in charge of starting NoSQL server but as remote process (in local machine) and stopping it. This will typically used during integration testing execution.


Second set of Rules are those responsible of maintaining database into known state. Each supported backend will have its own, and can be understood as a connection to defined database which will be used to execute the required operations for maintaining the stability of the system.

Note that because NoSQL databases are heterogeneous, each system will require its own implementation.

And finally two annotations are provided, @UsingDataSet and @ShouldMatchDataSet , (thank you so much Arquillian people for the name) to specify locations of datasets and expected datasets.


MongoDb Example

Now I am going to explain a very simple example of how to use NoSQLUnit, for full explanation of all features provided, please read documentation in link or download in pdf format.

To use NoSQLUnit with MongoDb you only need to add next dependency:

First step is defining which lifecycle management strategy is required for your tests. Depending on kind of test you are implementing (unit test, integration test, deployment test, ...) you will require an in-memory approach, managed approach or remote approach.

For this example we are going to use managed approach using ManagedMongoDb Rule) but note that in-memory MongoDb management is also supported (see documentation how).

Next step is configuring Mongodb rule in charge of maintaining MongoDb database into known state by inserting and deleting defined datasets. You must register MongoDbRule JUnit rule class, which requires a configuration parameter with information like host, port or database name.

To make developer's life easier and code more readable, a fluent interface can be used to create these configuration objects.

Let's see the code:

First thing is a simple POJO class that will be used as model class:

Next business class is the responsible of managing access to MongoDb server:


And now it is time for testing. In next test we are going to validate that a book is inserted correctly into database.

See that first of all we are creating using ClassRule annotation a managed connection to MongoDb server. In this case we are configuring MongoDb path programmatically, but also can be set from MONGO_HOME environment variable. See here full description of all available parameters.

This Rule will be executed when test is loaded and will start a MongoDb instance. Also will shutdown the server when all tests have been executed.

Next Rule is executed before any test method, and is responsible of maintaining database into known state. Note that we are only configuring working database, in this case the test one.

And finally we annotate method test with @UsingDataSet indicating where to find data to be inserted before execution of each test, and @ShouldMatchDataSet locating expected dataset.



We are setting an initial dataset in file initialData.json located at classpath com/lordofthejars/nosqlunit/demo/mongodb/initialData.json and expected dataset called expectedData.json.


Final Notes

Although NoSQLUnit is at early stages, the part of MongoDb is almost finished, in next releases new features and of course new databases will be supported. Next NoSQL supported engines will be Neo4J, Cassandra, HBase and CouchDb.

Also read the documentation where you will find an full explanation of each feature explained here.

And finally any suggestion you have, any recommendation, or any advice will be welcomed.


Stay In Touch


Email: asotobu at gmail.com

Blog: Lord Of The Jars
Twitter: @alexsotob
Github: NoSQLUnit Github

Keep Learning,
Alex

Full Code
Music: http://www.youtube.com/watch?v=8y5CbeHY7X0

jueves, mayo 24, 2012

I'm guided by this birthmark on my skin, I'm guided by the beauty of our weapons, First we take Manhattan, then we take Berlin (First We Take Manhattan - Leonard Cohen)




On May 23, I was at Berlin as speaker in LinuxTag. I talked about how to test modern Enterprise Java Applications using open source tools.

Presentation abstract was:

Ten years ago to present, Enterprise Java Applications have suffered many changes. We have moved from Enterprise Applications built with JSP+Servlet and EJB, to much more complex applications. Nowadays with the advent of HTML5 or JavaScript libraries like JQuery, client side development has changed significantly. With the emergence of web frameworks like Spring MVC or JSF,  server side code has quite changed compared to the one used when each web-form was mapped to a Servlet. And also persistence layer has changed with Java Persistence standard or with new database approaches like Data-Grid, Key-Values stores or Document stores.
Moreover, architectural changes have occurred too, REST-web applications have grown in popularity or AJAX is used to create asynchronous web applications. Due to development of Enterprise Java Applications have changed during these years, so testing frameworks have changed accordantly. The main topic of this speech will be how to test Enterprise Java Applications using these new frameworks.
In the first part of this presentation we are going to explore how to test JavaScript written on client side, how to write unit tests of server side code, and how to validate persistence layer. Next part of presentation will be focused on how to write integration tests on server side and acceptance tests on full Enterprise Java Applications (joining client and server side) and an introduction about testing REST-web applications. Finally we will show how to integrate all kind of test on your continuous integration system and run acceptance tests on test environment.

Session will combine theory with interactive practice using only open-source projects.

I have uploaded slides to slideshare so you can  take a look (sorry for red and blue colours):

How to Test Enterprise Java Applications
View more presentations from Alex Soto

Also if you want you can download the code that it was used in demo sections.

Javascript Unit Testing with JS Test Driver
NoSQL Unit Testing with NoSQLUnit
Integration Tests with Arquillian
Acceptance Tests with Thucydides

Please let me warn you that NoSQLUnit is an open source project that I am developing, and it is on early stages, in next month, project will have a better look by supporting more NoSQL systems like Neo4j, Cassandra or CouchDb and having an official (not snapshot) release. If you want you can follow me on Twitter or subscribing to NoSQLUnit github repository and receive the last news of this JUnit extension.

For any question do not hesitate to write them in comments section or sending me an email.

I would like to say thank you to linuxtag folks for treating me so well and all people who came to presentation, for all of them a big thank you.

Music: http://www.youtube.com/watch?v=JTTC_fD598A&ob=av2e

domingo, noviembre 14, 2010

What Colour is God? Why Can't You Tell Me.

Usually one tend to think about testing as a residual part of development. Nothing further from reality. Testing, so JUnit classes, needs to be treated as "business code". Must follow naming conventions, code must be sectioned, and of course must be readable. For this reason, John Ferguson Smart has its own rules that I would like to summarize and comment:

As John Ferguson Smart told in his entries, there are 5 rules that all JUnit classes must follows, that rules are:

I. Don't say "test", say "should".


JUnit test should pass, but "should pass", maybe there is something wrong in classes that makes test fail, for this reason we are writing off tests. Also, test cases must be validated with requirements, because a requirement is specified as should/shall not with test, same nomenclature is used. Thanks of this improvement, it is easy validating requirements using tests.

Also as Neal Ford suggests each word of your test method name must be separated with '_' character. I find this suggestion so useful because you don't need to use your mind for parsing camel case methods. Of course this only applies to JUnit methods (Yes the only exception between delivery classes and test classes). With this small change your test department will be thankful how fast can validate requirements.

For example the method: testTransfer must be changed to transferShouldDeductSumFromSourceAccountBalance as John Smart suggests, but another change is better, and is changing to: transfer_Should_Deduct_Sum_From_Source_Account_Balance and that's more readable.

II. Don't test classes, test their behavior.


Of course because test cases are related to use cases, tests must validate behavior. This also affects on avoiding testing your classes for the only porpouse of reaching 100% of coverage. 100% of coverage is important, but guarantees nothing, if you don't keep in mind that you must test behavior.

III. Test class names are important too.


Of course when you want to locate where some behavior is tested, it helps the name of your test. Class names must answer the question: When is this behavior applicable? as method names should answer the question: What behavior are we testing?.

What you think is better test class name: TransactionTest or WhenMoneyTransactionIsCommited. Both test names are valid but second one is descriptive about what behavior are you testing.

IV. Structure your tests well.


Test classes are also business classes and for that reason they also have the right to be refactored, kept clean and readable. For that reason is so important to write tests consistently. A really good suggestion is divide each test in three main sections, Given-When-Then. Only with tabs and CR can work perfectly, but you can also use frameworks like JBehave or Easyb.

V. Test are deliverables too.


Tests must be treated as commercial code, not because your client does not see test classes, you can ignore them from static analysis.