A Simple Hibernate, MySQL, and JUnit Tutorial


Getting Started With Hibernate and MySQL

In this tutorial, we’re once again going to use JUnit as a learning tool for exploring various Java technologies — in this case Hibernate. We’ll be configuring Hibernate to run with MySQL in a way that works both in a standalone application or in a Spring or other web application. Along the way we’ll also be setting up Log4J logging for hibernate. We’ll work on a small generics class that — although it doesn’t really do much more than wrap a few Hibernate functions — will allow us to demonstrate and test out the basic CRUD operations — Create, Read, Update, and Delete.

As usual, you can download the complete project files for IntelliJ Idea from our Tutorials Repository on Github. This tutorial is located in the HibernateGeneric directory. If you’re using Eclipse, check out our Eclipse instructions.


Configuring MySQL

This tutorial assumes you have mysql installed and can log in as root. If you don’t have MySQL on your system, you should start here and work through the instructions appropriate to your environment. Go into the mysql monitor (i.e., the mysql command line client). To do this, run:

<PathToMySQLBin>\mysql.exe –user=root –password=YourRootPassword

(If you haven’t set a mysql root password, you should — if you haven’t, you can simply use the command:

<PathToMySQLBin>\mysql.exe –user=root

Once you’re connected in the mysql client, use the source command to run the dbsetup.sql script located in the database directory of the tutorial, for example:

source database\dbsetup.sql

CREATE DATABASE tutorials;
USE tutorials;
GRANT ALL ON tutorials.* TO 'myuser'@'localhost' IDENTIFIED BY 'mypassword';
commit;
FLUSH privileges;

Of course, the user name and password given in this script are pretty brain-dead and certainly not secure so probably want to change them. If you do, that’s fine, you’ll just need to make one other change, in the hibernate configuration file. Let’s look at that next:


Configuring Hibernate

The hibernate configuration file is the file hibernate.cfg.xml in the root of the resources directory (i.e., at src/main/resources). As you can see, we’ve configured the JDBC driver directly in this file. If you changed the user name or password in the dbsetup.sql script, you need to make the corresponding chagnes to the “connection.username” and / or “connection.password” properties below.

You might also experiment with setting the show_sql and use_sql_comments to true, especially if you run into problems. For now they are turned off to keep the test run output a little bit cleaner.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/tutorials</property>
        <property name="connection.username">myuser</property>
        <property name="connection.password">mypassword</property>

        <!-- JDBC connection pool (use the built-in connection pool) -->
        <property name="connection.pool_size">1</property>

        <!--
            SQL dialect
            There are other mysql dialects avaialable IF you run INTO trouble WITH this one.
            The FULL list IS:
                MySQL5Dialect
                MySQL5InnoDBDialect
                MySQLDialect
                MySQLInnoDBDialect
                MySQLMyISAMDialect
            See http://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/dialect/package-summary.html
        -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

        <!-- Change these values to true to echo all executed SQL to stdout -->
        <property name="show_sql">false</property>
        <property name="use_sql_comments">false</property>

        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

        <!-- This is the entity class that we'll be testing. -->
        <mapping class="com.codesolid.tutorials.model.entities.Actor"/>

    </session-factory>
</hibernate-configuration>

I won’t post the log4j configuration here. Hibernate issues a warning if logging is not enabled, so I have configured Hibernate to use the log file, “log4j.log” in the root of the project directory. The configuration file for log4j is at src/main/resources/log4j.xml.


Minimizing Setup Time

As with any process that initially connects to a database, initializing Hibernate sessions takes a fair amount of time, and is not something you want to be doing over and over again in your tests. In the case of Hibernate, creating the SessionFactory object takes even more time, adding up to about 1.4 seconds on a laptop, or about .8 seconds on a faster machine. We don’t want to be running that for every test class. (To be sure, in the kind of one-class suite we’re running in this tutorial, it wouldn’t make a difference, but one of the purposes of these tutorials is to give you steal-able code that you can use in larger projects. What we want is to initialize the SessionFactory only once.

The Hibernate tutorial that comes with the Hibernate docs gives us a part of the solution, the HibernateUtil class, which exists for the sole purpose of ensuring a one time initialization of a SessionFactory, which it then caches as a static object. I’ve used this class pretty much verbatim in the current tutorial, changing only the package name.

// This file is adapted with only minor changes from the original in the hibernate
// tutorial, http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/tutorial.html.
package com.codesolid.tutorials.model.dal;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

}

OK, so we have a class where we can cache our SessionFactory, but the question remains — how should we wire that up to our JUnit tests? Since JUnit 4.9, we can use the @ClassRule annotation to set up a test suite with before and after methods that will run before and after all the classes in the suite have run. This allows for the initialization of expensive resoures once before all the tests in the suite are run.

The following listing shows the RuleSuite test suite, which builds with the rest of the tests in the src\test\java\code\codesolid\tests directory:

package com.codesolid.tests;

import com.codesolid.tutorials.model.dal.HibernateUtil;
import org.apache.log4j.Level;
import org.apache.log4j.xml.Log4jEntityResolver;
import org.junit.ClassRule;
import org.junit.rules.ExternalResource;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.apache.log4j.Logger;

@RunWith( Suite.class )
@Suite.SuiteClasses( {
        TestStorage.class
        /* , Add more test classes here separated by commas*/
} )
public class RuleSuite{

    static HibernateUtil util;

    // This is a static field.  Per the ClassRule documentation,
    // to use a ClassRule we need a field that is "public, static,
    // and a subtype of of TestRule."
    // See http://junit.czweb.org/apidocs/org/junit/ClassRule.html
    @ClassRule
    public static ExternalResource testRule = new ExternalResource(){
        @Override
        protected void before() throws Throwable{
            Logger.getLogger("com.codesolid.tests").log(Level.DEBUG, "Inside RuleSuite::ExternalResource::before.");
            util = new HibernateUtil();
        };

        @Override
        protected void after(){
            // Nothing to do here in this case.
            Logger.getLogger("com.codesolid.tests").log(Level.DEBUG, "Inside RuleSuite::ExternalResource::after.");
        };
    };
}

I’ve added some logging methods so you can see that the before and after methods are run only once at the start and end of the suite.


A Simple Hibernate Entity

In order to have an entity to save, I created an “Actor” entity. This represents a user in the system, but I’ve named the class “Actor” to avoid any potential conflict with the SQL keyword by the same name. I am using Hibernate annotations to define the entity.

@Table allows us to name the table.
@Entity marks the class as representing a Hibernate Entity, that is to say, an object that Hibernate can save to and load from the database.

For the Id primary key field, we use the following Hibernate annotations to mark the field as the primary key and to auto-increment the field for each new record:

@Id
@GeneratedValue(generator=”increment”)
@GenericGenerator(name=”increment”, strategy = “increment”)

Finally, we used the column annotation to explicitly set the field name for the Role property to “user_role”:

@Column(name=”user_role”)

/**
 * Class Actor
 * Description:  A user of the system, the subject of a user story.  We use
 *               actor instead of user as table name to avoid any conflict
 *               with the database concept of user
 */

package com.codesolid.tutorials.model.entities;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;

@Table( name = "ACTORS" )
@Entity
public class Actor {
    public static final String DEFAULT_ROLE = "Standard User";

    public Actor() {
        setRole(Actor.DEFAULT_ROLE);
    }

    private Long id;
    private String role;

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }


    @Column(name="user_role")
    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

The final step to making the Entity work is one that’s easy to forget, but as we saw when we discussed the hibernate.cfg.xml file, make sure you include a mapping to the entity class, as we show again below:

<!-- This is the entity class that we'll be testing. -->
<mapping class="com.codesolid.tutorials.model.entities.Actor"/>


A Hibernate Generic Entity Storage Class

While working with Hibernate enitities, it struck me that many of the basic operations one might do with an entity could be captured well in a generic class, which is what we’ll be using to test here. As you can see below, each of the methods was pretty much a wrapper around a single Hibernate session call — with the exception of BeginTransaction, which combines getting the session from the session factory and starting the transaction.

package com.codesolid.tutorials.model.dal;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Storage <T > {

    public static SessionFactory getSessionFactory() {
        return HibernateUtil.getSessionFactory();
    }

    private T entity;
    private Session session;

    public void beginTransaction() {
        session = Storage.getSessionFactory().getCurrentSession();
        session.beginTransaction();
    }

    public void commit () {
        session.getTransaction().commit();
    }

    public Storage(T entity) {
        this.entity = entity;
    }

    public void update(T entity) {
        session.update(entity);
    }

    public Long insert(T entity) {
        return (Long) session.save(entity);
    }

    public void delete(T entity) {
        session.delete(entity);
    }

    // This call will issue a warning about the unchecked cast,
    // but we know the value returned will be of the right type because
    // we specify the entity (T) class in the call.
    //
    // Note that "get" will return a null if no value with this id fails
    @SuppressWarnings (value="unchecked")
    public T getById(Long id) {
        return (T) session.get(entity.getClass(), id);        
    }
}

Taken together, this class and the unit tests I wrote for it were a good way to discover a couple of interesting Hibernate gotchas. The first Hibernate mine that I steped on was that objects are no longer usable outside the context of a transaction. Before my testing uncovered this, my original implementation of getById was called loadById, and the implementation and test looked something like this:

  // Implementation  
    public T getById(Long id) {
        storage.beginTransaction();
        T obj = (T) session.load(entity.getClass(), id);
        session.getTransaction().commit();
        return obj;
    }

   // Test code:
   // ...
   Actor actor  = storage.getById(id);
   assertEquals(actor.getRole(), "Some Role");

This seemed like a safe approach (albeit not an efficient one since each call is wrapped in a transaction). As it turns out, because Hibernate uses lazy initialization, the object returned from getById needed to still have the transaction active. As a result, I got the following exception:

org.hibernate.LazyInitializationException: could not initialize proxy – no Session

This caused me to push the transaction management out to the client, so I exposed beginTransaction and commit methods on my storage class.

At that point, the code and test looked like:

// Implmentation
public T getById(Long id) {
    return (T) session.load(entity.getClass(), id);
}

// Test code
storage.beginTransaction();
Actor actor  = storage.getById(id);
assertEquals(actor.getRole(), "Some Role");
storage.commit();

The second interesting Hibernate quirk that I ran into was in trying to test my delete method. Originally I wrote the test by deleting an object and then checking for the ObjectNotFoundException when I called loadById in an effort to reload the deleted object. The first time I ran it, that test passed, but a few minutes later it failed. It turns out that loadById may or may not return an ObjectNotFoundException, or it may instead return a “proxy object”, though I admit I have a bit of a hard time following the architectural genius behind the decision to return a proxy to an object that doesn’t exist yet — or in this case, doesn’t exist any more. At that time I researched it and found that getById has the more reasonable behavior of reliably returning a for objects that don’t exist, so the test and the code evolved accordingly.


The JUnit Test


With that, the final form of the JUnit test is below. Even though I’m showing it last, in reality the process was more test-first, going back and forth between the tests, the configuration, and the classes under development.

package com.codesolid.tests;

import com.codesolid.tutorials.model.entities.*;
import com.codesolid.tutorials.model.dal.Storage;
import org.junit.Test;
import static org.junit.Assert.*;

public class TestStorage {

    @Test
    public void testWrite() {
        // Just a write, verify id set
        Actor user = new Actor();
        Storage<Actor> storage = new Storage<Actor>(user);
        storage.beginTransaction();
        user.setRole("SuperUser");
        assertNull(user.getId());
        storage.insert(user);
        assertNotNull(user.getId());
        storage.commit();
    }

    @Test
    public void testWriteAndRead() {

        // This time write and read back
        String overRideRole = "SuperUser";

        // Write
        Actor actor = new Actor();
        Storage<Actor> storage = new Storage<Actor>(actor);
        storage.beginTransaction();
        actor.setRole(overRideRole);
        assertNull(actor.getId());
        storage.insert(actor);
        assertNotNull(actor.getId());
        Long id = actor.getId();
        storage.commit();

        // Read and verify
        Actor actor2  = new Actor();
        assertEquals(actor2.getRole(), Actor.DEFAULT_ROLE);
        storage = new Storage<Actor>(actor2);
        storage.beginTransaction();
        actor2 = storage.getById(id);
        assertEquals(actor2.getRole(), overRideRole);
        storage.commit();
    }


    @Test
    public void testUpdate() {

        String overRideRole = "SuperUser";
        String newOverrideRole = "GUEST";

        // Insert an actor
        Actor actor = new Actor();
        Storage<Actor> storage = new Storage<Actor>(actor);
        storage.beginTransaction();
        actor.setRole(overRideRole);
        assertNull(actor.getId());
        storage.insert(actor);
        assertNotNull(actor.getId());
        Long id = actor.getId();
        storage.commit();

        // Read it back
        Actor actor2  = new Actor();
        assertEquals(actor2.getRole(), Actor.DEFAULT_ROLE);
        storage.beginTransaction();
        actor2 = storage.getById(id);
        assertEquals(actor2.getRole(), overRideRole);

        // Update it
        actor2.setRole(newOverrideRole);
        storage.update(actor2);
        storage.commit();

        // Read it again and verify update
        storage.beginTransaction();
        Actor actor3  = storage.getById(id);
        assertEquals(actor3.getRole(), newOverrideRole);
        storage.commit();
    }

    @Test
    public void testDelete() {

        Actor actor = new Actor();
        Storage<Actor> storage = new Storage<Actor>(actor);

        // Write
        storage.beginTransaction();
        storage.insert(actor);
        Long id = actor.getId();
        storage.commit();

        // Delete it now
        assert(actor.getId() > 0);
        storage.beginTransaction();
        storage.delete(actor);
        storage.commit();

        // Now we can't read it back, as expected
        storage.beginTransaction();
        Actor actor2 = storage.getById(id);
        assertNull(actor2);
        storage.commit();
    }
}
Tagged with: , , , ,
Posted in Tutorials

How to Run the CodeSolid Tutorials in Eclipse

If you’ve taken a look at the Github Repository for the CodeSolid tutorials, you may have noticed that the project files all use IntelliJ Idea.  I use the Ultimate Edition (currently Version 12) for most of my development, but recently I promised to look into using these project files in Eclipse.  I had a feeling it would work since I have sourced the Maven project — i.e., the POM files, those named pom.xml in the root of each tutorial — but being the good test infected developer that I am, I try not to take “that should work” for granted.

Well, the good news in this case is that not only should it work, but it actually does.  I have tested it out on the Spring Tool Suite version 3.2, as well as on a more vanilla version of Eclipse (Indigo — version 3.7).  Because we’re importing Maven files, Maven is resolving the dependencies — meaning the Spring Tutorial works even without the Spring Tool Suite.  (How cool is that — it’s magic!)  To run the projects, start by right clicking on any empty space in the Package Explorer window, as shown below.


EclipseImport

 

From the menu, select Import.  In the Import dialog box, you want to select Maven, then Existing Maven Project, as shown below:

EclipseImport2

If you then navigate to the root of the tutorials directory, you can select which tutorials you want to import.  I’m writing this article when there are only two tutorials available — you’ll likely see more projects available.  Select the project(s) you want, click finish, and you’re done!  You can now run the tutorials in Eclipse.  Enjoy!

EclipseImport3

Tagged with: , , , ,
Posted in Tutorials

Spring Unit Testing Using JUnit

Exploring the IDE Starter Project

In this tutorial we’ll set up some really basic Spring unit tests — the sort of thing that is vanilla enough so you can steal it and get started on your own tests. I developed these tests in IntelliJ Idea Ultimate Edition, but when I check them in to the Github repository I’ll try to make something available in Maven and Eclipse, so you can try it out that way if you like. (Update — that’s done, here are the instructions).  I originally developed these tests in a web app I was working on, but to keep things simple let’s start instead by creating a new project in Idea as a “Spring Application” for the project type.

Spring Starter Project in IntelliJ

You can then make the project from the build menu, and you’ll see if you look around in the test directory (actually src\test\java\foo.bar, to be precise), that Idea has created your first Spring Test for you as SpringAppTests.java:

package foo.bar;

import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config.xml")
public class SpringAppTests {
@Autowired
private HelloService helloService;

@Test
public void testSayHello() {
Assert.assertEquals("Hello world!", helloService.sayHello());
}
}

This unit test is doing a few interesting things. First of all, it’s annotated as “@RunWith(SpringJUnit4ClassRunner.class)”. The Spring JUnit runner, which works in conjunction with the Spring TestContextManager, allows you to easily set up Spring ApplicationContexts for your tests, as you can see it does here with the annotation @ContextConfiguration(“classpath:spring-config.xml”). Inside the SpringAppTests class, you can see that you can also use Dependency Injection to wire up your objects for you. Note that the object that’s under the @Autowired annotation is used in the test without an explicit constructor call.

Testing Some Basic Spring Beans

Now let’s write our own test to exercise some basic beans to see how the Spring framework injects dependencies as needed. We’ll want to compare that to what would happen outside of the framework so we’ll set up our beans in such a way as to work differently depending on the context — Spring versus non-Spring. (I was tempted to say Spring versus Fall in that last sentence, but Java suffers from enough puns already).

Let’s say we want to model some classes to capture software User Stories. Of course, every story needs a character, so we’ll want a class to model the person using the software. One very useful form of user story takes the basic form: As a <Type of User> I want to <Something the software can do> in order that <some benefit to the user>.

So let’s write two beans to capture the relationship between a user and the UserStory. First, the UserStory class:

// UserStory.java

package com.codesolid.tutorials;

/**
* Class UserStory
* Description: An example bean that models a user story.
* Uses the standard story form:
* "As a ______" (user role), "I want to ______" (actionDesired)
* "so that _____" (outcomeDesired).
*/

public class UserStory {
private User user;
private String actionDesired = "";
private String outcomeDesired = "";
public UserStory() {
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

public String getActionDesired() {
return actionDesired;
}

public void setActionDesired(String actionDesired) {
this.actionDesired = actionDesired;
}

public String getOutcomeDesired() {
return outcomeDesired;
}

public void setOutcomeDesired(String outcomeDesired) {
this.outcomeDesired = outcomeDesired;
}
}

And the User class:

package com.codesolid.tutorials;

/**
* Class User
* Description: An example of a bean dependency. Story is dependent on Actor.
*/

public class User {
private String role;

public User() {
setRole("User");
}

public String getRole() {
return role;
}

public void setRole(String role) {
this.role = role;
}
}

As you can see, if you were to construct a UserStory object at this point, the user field it contains would be null. The trade-off on class dependencies is basically this: You can ensure that your objects are always fully constructed by putting all the dependencies in the constructor. However, this means that your object becomes tightly coupled with other objects, and harder to test. Having accessors to set the dependencies means you have the flexibility to test only that part of the object that relies on the dependencies, or you can set up all your dependencies up front and test a fully constructed object.

Spring can inject the dependencies either way, but many people prefer using the accessors using what’s known as “Setter Based Dependency Injection”.

Take a look at the file src\main\resources\spring-config.xml. Here we’ve configured the dependency using XML. (Spring also allows this to be done using annotations, but we won’t cover that in this tutorial):

When we add our dependencies, the file looks like this:

<!--?xml version="1.0" encoding="UTF-8"?-->
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"&gt;
<!-- Our dependencies -->

We’re now ready to write some tests against this code. I’ll show you the whole listing in one go, since I’ve commented it fairly heavily to show what we’re demonstrating in each case. Bear with the imports — there’s some code underneath, I promise!

package com.codesolid.tutorials.tests;

import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.context.ApplicationContext;
import com.codesolid.tutorials.UserStory;
import com.codesolid.tutorials.User;
import static org.junit.Assert.assertEquals;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/resources/spring-config.xml")
public class ContextTests {

@SuppressWarnings("SpringJavaAutowiringInspection")
@Autowired
protected ApplicationContext ac;

// Using ApplicationContext
// The getBean method is the workhorse of the Spring ApplicationContext.
// The user field in the UserStory object was set up (dependency injected)
// by Spring:
@Test
public void testUserNotNull() {
UserStory story = (UserStory) ac.getBean("userStory");
assertNotNull(story.getUser());
}

// Not using ApplicationContext
// Regular non-Spring instantiation
// Instantiating our own UserStory, you can see that the user
// is null.
@Test
public void testUserStoryNotFromContext() {
UserStory story = new UserStory();
assertNull(story.getUser());
}

// Not using ApplicationContext
// Regular non-Spring instantiation
// The default role if you just call the constructor
// is "User".
@Test
public void testNonSpringUserDefaultRole()
{
User u = new User();
assertEquals(u.getRole(), "User");
}

// Using ApplicationContext
// Since Spring instantiated this according to the property
// from spring-config.xml, it overrode the default "user"
// role with "SuperGenius User". (This presumably
// is Wile E. Coyote.)
@Test
public void testUserRoleIsAsExpected() {
UserStory story = (UserStory) ac.getBean("userStory");
assertEquals(story.getUser().getRole(), "SuperGenius User");
}
}

As you can see, Spring allows for a great deal of flexibility in configuring the objects in the system. In a simple context like this one it may be hard to see the advantage of this, but in the context of a large application, having a configuration system like this in place means that the system is very flexible.

Getting an Application Context in a junit.org Test Runner

You’ll probably use the SpringJUnit4ClassRunner for most of your Spring testing, since it is derived from the “vanilla”, junit.orgJ Unit4ClassRunner. However it’s also possible to get an ApplicationContext outside of the context of the Spring test runner, and doing this in JUnit demonstrates how to achieve this programatically. The following sample shows some of the same tests we ran earlier set up in this way:

package com.codesolid.tutorials.tests;
import com.codesolid.tutorials.UserStory;
import org.junit.Test;
import org.junit.Before;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import static org.junit.Assert.*;

/* Here we run one of the same tests we run in ContextTests, but we separate it out here to demonstrate
* we can do it with a POJU (Plain Old JUnit :) test runner.
*/

public class JUnitContextTests {

ApplicationContext ac;

@Before
public void setUp()
{
ac = new FileSystemXmlApplicationContext("file:src/main/resources/spring-config.xml");
}

@Test
public void testUserCorrectFromPlainOldJUnitTest() {

UserStory story = (UserStory) ac.getBean("userStory");
// Spring is working fine using this app context
assertEquals(story.getUser().getRole(), "SuperGenius User");

// In this case our User is not wired up
UserStory story2 = new UserStory();
assertNull(story2.getUser());
}

@Test
public void testPrewiredUserCorrect() {
UserStory story = (UserStory) ac.getBean("userStory");
assertEquals(story.getUser().getRole(), "SuperGenius User");
}
}

I hope you enjoyed this tutorial on Spring Unit Testing — feel free to leave a comment if you’re finding it useful.

Tagged with: , , , ,
Posted in Tutorials

Pros and Cons of Test Driven Development

If you ask anyone who works with me, I’m a huge fan of automated unit testing in general and test driven development (TDD) in particular. Ever since I first tried it out on a project eleven years ago, I’ve been convinced that using automated unit tests to drive new projects and improve existing ones is a huge improvement over the number one software development “methodology” in the U.S.: code and fix. But if TDD is so cool, the last sentence begs a very important question: why is code and fix so popular? If you’re a software development manager, should you be considering more unit testing for your next project, or do you find that you’re getting good results without it? Are there legitimate reasons not to consider automated unit testing? How much testing is enough?  What are the pros and cons of Test Driven Development and automated unit testing?

Pros

  • If you’re a software manager, the number one benefit to consider for automated unit testing is reduced costs. This may seem paradoxical — how can writing more code cost you less? The answer is that unit tests let your developers find bugs earlier in the development process than they would otherwise.  As a result of this, empirical studies such as the one conducted by Nagappan et al. at Microsoft and IBM have shown a drop in the defect density of between 40% and 90% for teams using test driven development.
  • The value of unit tests as a safety net  is especially true when the code needs to be changed to either add new features or fix an existing bug, since the  sanity check for new changes.  Since the maintenance phase of the software effort has been estimated to make up between 60 and 90% of the software lifecycle, it’s hard to overstate how the time taken up front to create  a decent set of unit tests can pay for itself over and over again over the lifetime of the project.
  • To me as a developer another big plus to automated unit testing is something that rarely gets much mention but is crucially important. Writing unit tests while you’re developing code means you’ll always have a stub for exercising a given method in the debugger. Getting my start a 20,000 years ago as I did as a C and C++ programmer — there be pointers there! — running your code through the debugger as you were writing it was something that All-Right-Thinking-Programmers(tm) have to do. As my friend, Jim Alisago, put it early on in my career, “You might as well start in the debugger because you’re going to end up there anyway.” I sometimes get the impression reading the literature that Unit Testing replaces debugging — on the contrary, to me, it enables it and enhances it.
  • Another way to make the above point is that it forces you to try to make your interfaces clean enough to be tested. It’s sometimes hard to see the advantage of this until you work on a body of code where it wasn’t done, and the only way to exercise and focus on a given piece of code is to run the whole system and set a break-point. Unit tested code therefore tends to be less tightly coupled than code that sprang fully formed from the clever mind of a cowboy developer.  This in turn makes it easier to test.
  • Unit tests are a fantastic learning tool for developers using new technologies. Whenever I encounter something obtuse in some bit of software documentation, I find myself reaching for a small set of unit tests. Unit tests let me quickly find where the skeletons are buried in a new framework.
  • Along the same lines serve as documentation for existing code, showing developers new to the code how it works.

Cons

  • There is of course the up front cost of writing the unit tests.   I believe that in almost all cases this cost will be amortized over the life of the project.  However, if a quick and dirty prototype is needed in a hurry, this initial time cost may not be acceptable.  A caveat is in order here, however:  too many a quick and dirty prototype has been rushed from developer conference to deliverable without stopping at go or collecting $200.  Today’s quick and dirty prototype is often tomorrow’s legacy albatross.
  • Speaking of legacy code, it is far, far easier to introduce unit testing at the start of a coding effort than it is to add unit tests during the maintenance phase of a project.  It’s more difficult enough that Michael Feathers was able to write a wonderful book about it.  However, as the Chinese are alleged to say, the best time to plant a tree was 20 years ago, but the second best time is today.
  • Like any good technique, unit testing can be carried to an extreme — though I daresay it hasn’t been my good fortune to work on a team where that happened.  My own experience has been that the biggest benefit to unit testing comes from a moderate effort, with the tests always exercising the code in the simplest way possible.  If you find yourself frequently re-factoring your tests, there’s a good chance you’re spending too much time on the test suite.  Similarly, there’s not much point to optimizing your tests with stubs and mocks if they don’t take that long to run yet.  Remember, you ain’t gonna need it.  The finger pointing to the moon is not the moon.
  • Unit tests of course need to be maintained to be useful — ideally keeping the error / failure rate at zero.  This of course means there are times when the tests themselves have to change to keep track of new changes to the code, but the whole point of the test suite is to bring the impact of your changes into sharp focus.  Breaking existing callers depending on an interface is not a big deal — but doing it without knowing you did it is a real problem.
  • Unit tests are just unit tests.  Although, as we mentioned above, they do have a role in documentation, unit tests are  not a substitute for documentation.  Contrary to what many agile texts (an oxymoron?) would have you believe, not all comments are “smells”, and the thinking about what the software should do that takes place in the process of producing initial specifications almost always justifies a reasonable effort.  Nor are unit tests a substitute for integration testing, acceptance testing, or other automated / manual testing done by sharp quality engineers.
Tagged with: , ,
Posted in Software

A Simple JUnit Tutorial using Maven and IntelliJ Idea


What is JUnit?

JUnit is a powerful and easy to use tool that every Java programmer should know.  It’s a unit test framework That is to say, it’s a framework for testing out small pieces of code, such as individual classes and methods, as the code is being developed.

For those newcomers to Java who aren’t familiar with JUnit, Here is a really simple, “Hello World” style tutorial about how to use JUnit with Maven and IntelliJ Idea Community Edition — both free tools. By the way, this tutorial also works fine with the professional edition.

Get The Tools

If you need to set up those tools, here are the  IntelliJ Idea download page and the Maven Download / Installation page. Be sure to read the installation page carefully in the case of Maven especially

Set up the Maven Project

Though it may seem counter-intuitive, I find that the easiest way to start with Maven and Idea projects is not to start in Idea, but to simply to save a maven project file (“pom.xml”) in a text editor.  Here is that file:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.particlewave</groupId>
    <artifactId>HelloJUnit</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>


Run In Maven

Save the file above using a plain text editor in a new directory that will be the root directory of you project, then open a command prompt at that location.  Enter the command  ”mvn -q install”

If you’re new to Maven, the cool thing about it is that it will install any dependencies your project needs, so if the universe is behaving as it should you should see output that looks something like:

[debug] execute contextualize
[debug] execute contextualize

--------------------------------------------------
 T E S T S
--------------------------------------------------

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

You’ll notice no tests were run — that’s as expected, since we haven’t written them yet! Before we do, while still at the command line there’s one more manual step we have to do, and that’s to set up our directory structure in a way that Maven expects it. On Windows the command is:

md src\main\java
md src\main\resources
md src\test\java
md src\test\resources

On Unix or a Mac the command would be:

mkdir -p src/main/java
mkdir -p src/main/resources
mkdir -p src/test/java
mkdir -p src/test/resources


Importing the Project Into Idea

At this point you’re ready to open the Idea IDE. Now we’re going to create an Idea project by importing the maven file we just created. Click on Import Project, and then navigate to where you have that pom file stored. It should look something like:

On the first dialog that comes up, I usually like to check the box that says “Import Maven projects automatically”, as shown below.

You’ll then click through a few more dialog boxes, selecting the default for each. On the one that asks you to select a JVM, make sure it looks like a valid one is selected.

Once you’ve imported the project, locate the project view on the left, and navigate to the src\test\java directory, as shown below:



Your First Test

Right click on the src\test\java directory, and select New / File. Give it the name “TestHello.java”, and paste the following code into it:

import org.junit.Test;
import static org.junit.Assert.*;

public class TestHello {

    @Test
    public void testPasses() {
        String expected = "Hello, JUnit!";
        String hello = "Hello, JUnit!";
        assertEquals(hello, expected);
    }

    @Test
    public void testFails() {
        // The worlds most obvious bug:
        assertTrue(false);
    }

    @Test
    public void testArray() {
        int [] array1 = new int[] {1, 2, 3};
        int [] array2 = new int[] {1, 2, 3};
        assertArrayEquals(array1, array2);
    }
}


Building and Running the Tests

To build the test, from the Idea menu select “Build / Make Project”. Next, from the Run menu select Debug. If all goes well you should see a configuration named “Test Hello”. Click that.

Fixing a Bug

You will next see the output of the tests in a window that looks like this:

You may have noticed when you pasted the code that the testFails method contains “The world’s most obvious bug”. Because of this, that test will fail. You’ll notice that — very conveniently — there will be a link to TestHello.java:16 — clicking that link will bring you right to the failing line of code, where you should be able to fix it easily. Running tests in the debugger like this is a very easy way to fix the failing code.

Of course, these tests are very simple and do not test any “real” code. In a real project you’d be moving back between fixing the bugs in the code, which the test code was exercising, while writing new tests to exercise new code. But if you put your Java classes in src\main\java, you can easily test them from tests you add to src\test\java.

Enjoy!

Tagged with: , , , ,
Posted in Tutorials

What If Carpenters Were Hired Like Programmers?

If carpenters were hired like programmers, job ads might look like this:

Help Wanted, Carpenter.  

Skills Needed:

  • Familiarity with Craftsman brand hammers and saws.
  • Five to ten years of experience building round tables out of mahogany.
  • Familiarity with the full carpentry life cycle including sawing, hammering, etc.

Good to Have:

  • Experience building tables for free (open source tables).
  • Knowledge of square tables.
  • Pine experience.
Posted in Software