Five ‘s Weblog

October 16, 2007

An example of JMock!

Filed under: Programming — by powerdream5 @ 8:35 pm
Tags: , , ,

        Test-Driven Development(TDD) has already been proved to be a best practice for software ddevelopment. And In the process of TDD, we frequently come across such situation that one method has to communicate with other classes to realize its function. Therefore, in order to test this method, we have to create the class it is going to communicate with firstly. However, this will deviate from the concept of unit testing. Fortunately, we have some useful tools to handle this kind of situation, such as JMock and EasyMock, which can mock the objects the method interact with, so that we don’t need to crate a real object to finish the testing for that method.

10_16_3_2007.jpg

        Today, I am going to show an example of the use of JMock. Firstly, you need to download JMock and JUnit. Do not use the latesting version (junit 4.4) of JUnit. In this example, I use JUnit 4.3.1 and JMock 2.2. Then add the following packages into your classpath: junit-4.3.1.jar, jmock-2.2.-.jar, jmock-junit4-2.2.0.jar, hamcrest-core-1.1.jar and hamcrest-library-1.1.jar.
        I am going to create a small application which can say different greetings to the client according to different time. For example, it outputs “Good morning, ***” in the morning, and outputs “Good evening, ***” in the evening. According to the procedure of TDD, we firstly create a test case.

//import some necessary classes from the package of JUnit4
import org.junit.Test;
import static org.junit.Assert.asserEquals;

public class TestJMockCase{

   @Test
   public void testSayGreeting(){
         Greeting o = new Greeting();
         String out = o.SayGreeting(“wu cao”);
         assertEquals(“Good afternoon, wu cao”, out);
   } 
}

        Because we haven’t created the class of Greeting, we will fail in compiling this test case. In order to make it through compilation, we need to code the Greeting class. And we find the Greeting class have to communicate with the other class named GreetingTime to get the the words of greeting.

public class Greeting{
        //we have to define GreetingTime as an interface
        //I am goint to explain it in the later
        private GreetingTime gt;
        public void setGreetingTime(){
               this.gt = gt;
        }

        public String sayHello(){
               String greeting = gt.getGreeting();
               return greeting+”, “+name;  
        }

        In order to compile successfully, we also need to create the class of GreetingTime. But now, our focus is not on the GreetingTime class, so we decide to use mock object.

public interface GreetingTime{
        public String getGreeting();
}

       Because we are going to mock the GreetingTime class, we have to define it as an interface, which is a prerequisite for the mock object. Therefore, we have to use the setter method to inject the instance of GreetingTime to Greeting, (we cannot use the new keyword on an interface).

       Then, we have to make some changes to the test class we created before, because we are going to mock the GreetingTime.

//import some necessary classes from the package of JUnit4
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
//import some necessary classes from the package of JMock2.2
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.Expectations;
@RunWith(JMock.class)
public class TestJMockCaseUsingJMock{
        //create the context for the mock object
        Mockery context = new JUnit4Mockery();

        @Test
         public void testSayHello()
        {
             //Mock the GreetingTime class using the technology of reflection
             //you have to define it as a final variable
             //since it is going to be used in a inner class
             final GreetingTime gt = context.mock(GreetingTime.class);
             Greeting g = new Greeting();
              g.setGreetingTime(gt);

             //set the expection for the mock object
             context.checking(new Expectations(){{
                   //the mock object will call the getGreeting method once
                  //and we assume that is returns “Good afternoon”
                  one(gt).getGreeting(); will(returnValue(“Good afternoon”));
              }});

             String out = g.sayHello(“wu cao”);
             //compare the result and expected value
             assertEquals(“Good afternoon, wu cao”,out);
         }
}

Now, you can open the command widnow to test.

10_16_2_2007.jpg

10_16_1_2007.jpg

Blog at WordPress.com.