google Analytics

Wednesday, February 2, 2011

Mock Objects in Unit Tests

Mock Objects in Unit Tests

EasyMock is a well-known mock tool that can create a mock object for a given interface at runtime.
The mock object's behavior can be defined prior encountering the test code in the test case.
EasyMock is based on java.lang.reflect.Proxy,
which can create dynamic proxy classes/objects according to given interfaces.
But it has an inherent limitation from its use of Proxy: it can create mock objects only for interfaces.
Now Easy Mock Class Extension has come using that we can create Mock for the Classes Also

Life Cycle Control Methods
    public void replay();
    public void verify();
    public void reset();





Initially, the mock object is in the preparing state. The mock object's behavior can be defined in this state. replay()
changes the mock object's state to the working state.
All method invocations on the mock object in this state will follow the behavior defined in the preparing state.
After verify() is called, the mock object is in the checking state.
MockControl will compare the mock object's predefined behavior and actual behavior to see whether they match.
The match rule depends on which kind of MockControl is used; this will be explained in a moment.
The developer can use replay() to reuse the predefined behavior if needed.
Call reset(), in any state, to clear the history state and change to the initial preparing state.


Example:
========================================================================================================
The Interface
import java.io.IOException;
public interface Service {
    String sayHello();
    String writeToFile() throws IOException;
    void isVoidCallable();
}

========================================================================================================
import java.io.IOException;
import org.easymock.MockControl;
import org.junit.Test;
import junit.framework.TestCase;
import java.io.IOException;
import org.easymock.MockControl;
import org.junit.Test;
import junit.framework.TestCase;

public class ServiceTest extends TestCase {
   
    private MockControl mockControlService;
    private Service service;
   
    protected void setUp() throws Exception {
        super.setUp();
        mockControlService = MockControl.createControl(Service.class);
        service = (Service) mockControlService.getMock();
    }
   
    protected void tearDown() throws Exception {
        super.tearDown();
    }
   
    @Test
    public void testSayHello() throws Exception {
        this.mockControlService.reset();
        this.service.sayHello();
        mockControlService.expectAndReturn("sayHello", "Hello Anish");
        // Or it can be Used Like mockControlService.setDefaultReturnValue("Hello Anish");
        mockControlService.replay();
        String s = service.sayHello();
        assertEquals("Hello Anish", s);
        mockControlService.verify();
    }
   
    @Test
    public void testwriteToFile_IOException() throws Exception {
        this.mockControlService.reset();
        this.service.writeToFile();
        mockControlService.setThrowable(new IOException());
        mockControlService.replay();
        try {
            this.service.writeToFile();
            fail("Failed to Throw Exception");
        } catch (IOException e) {
            assertNotNull(e);
        }
        mockControlService.verify();
    }
   
    @Test
    public void testIsVoidCallable() throws Exception{
        this.mockControlService.reset();
        this.service.isVoidCallable();
        mockControlService.setVoidCallable();   
    }
}

==========================================================================================================
TESTING THE MDB
package com.test;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import com.test.DummyMDBTest.Employee;
public class DummyMDB implements MessageListener {
    @Override
    public void onMessage(Message inMessage) {
       
        try {
            if (inMessage instanceof ObjectMessage) {
                System.out.println("Type of Object Message");
                Employee e1= (Employee) ((ObjectMessage) inMessage).getObject();
                e1.getName();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
    }
}

import java.io.Serializable;
import javax.jms.ObjectMessage;
import org.easymock.MockControl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class DummyMDBTest {
    private MockControl objectMsgCtrl = null;
    private ObjectMessage objectMsg = null;
    private DummyMDB mdb;

    @Before
    public void setUp() throws Exception {
        objectMsgCtrl = MockControl.createControl(ObjectMessage.class);
        objectMsg = (ObjectMessage) objectMsgCtrl.getMock();
        mdb = new DummyMDB();
    }

    @After
    public void tearDown() throws Exception {
        objectMsgCtrl = null;
        objectMsg =null;
        mdb = null;
    }

    @Test
    public final void testOnMessage() throws Exception {
        this.objectMsgCtrl.reset();
        this.objectMsg.getObject();
        this.objectMsgCtrl.setReturnValue(new Employee());
        this.objectMsg.getObject();
        this.objectMsgCtrl.setReturnValue(new Employee());
        this.objectMsgCtrl.replay();
        this.objectMsg.getObject();
        mdb.onMessage(objectMsg);
        this.objectMsgCtrl.verify();
    }
   
    class Employee implements Serializable{
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
}

==========================================================================================================
ejb testing JUnit.
ejbtesting JUnit
Testing MDB Using JUNIT,
Mocking MDB Example
Easy Mock MDB example
Easy Mock Interface Example


--
ANish