Wednesday, September 28, 2011

Information about Mock and Stub

One of the common questions in interview,have you written test cases for your Java Code.If your code uses some other class,how you resolved this dependency.
Have you used Stubs or Mocks and whats the reason behind it?
Is there any difference between them?

Lets discuss this scenario and figure out when to use what.
Use Case
We have to create authentication module in our system.It checks for username and password and returns true or false depending upon whether username and password supplied is correct
or not.In our use case we have a LoginService which uses IUserDAO.There is a concrete class named UserDAO which implements IUserDAO and uses database table for doing authentication check.It will return success/failure as authentication result

So now if we have to write test case for LoginService authenticate () method.We need to provide some implementation for IUserDAO for test case to complete.We fake the IUserDAO  implementation by creating a mock or stub of it.

What is Stub?

Stub is a fake implementation of the dependent class.If we follow interface driven approach we can create a stub by implementing the interface and provide hard coded return values.
The basic idea is to implement the dependencies as concrete classes, which reveal only a small part of the overall behavior of the dependent class, which is needed by the class under test.

+ves
-There is no dependency on external jars.
-We are writing extra class having redundant implementation and hard coded return values for testing our api.
-Easy to simulate and understand

-ves
-If interface changes we have to modify the stubs.
-There could be multiple stub implementations for testing different  api's because if we use one stub class for all test case,we may break other test cases.
-If interface has many methods our stub will have lots of empty methods.

Above use case with Stub Implementation

 
package com.kunaal.stubMock.test;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

import com.kunaal.stubMock.dao.IUserDAO;
import com.kunaal.stubMock.service.LoginService;

/**
 * @author Kunaal A Trehan
 *
 */
public class LoginServiceTest {
	
	private LoginService loginService=new LoginService();
	
	/**
	 * Here we setting stub implementation for userDAO which we will use in this service
	 * So interface driven approach helps us to fake the dependency by injecting  
	 * stub[anonymous implementation of IUserDAO] of other class and let us test 
	 * our method  
	 */
	@Before
	public void stubSetup(){
		loginService.setUserDAO(new IUserDAO(){

			public boolean authenticate(String uName, String passWd) {
				if(uName!=null && uName.equals("Kunaal") && 
						passWd !=null && passWd.equals("Password"))
					return true;
				else
					return false;
			}
		});
	}
	
	
	@Test
	public void authenticate(){
		assertTrue(loginService.authenticate("Kunaal", "Password"));
		assertFalse(loginService.authenticate("Kunaal", "Kunaal"));
	}

}


What is Mock?


Mock also fake's the implementation .But in case of mock we record and verify the interaction between the two classes.Basic idea is to plug the expectation at the runtime and verify the same.

+ves

-No need to create an extra class for faking the implementation
-Relives us from having blank implementations for methods in case number of methods are huge.
-We can define the expectation at the run time
-We can verify whether the method in the dependent class has actually been invoked or not

-ves
-Need third party api for providing mocking behavior
-Its not straight forward to understand

Above use case with mock implementation

package com.kunaal.stubMock.test;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import com.kunaal.stubMock.dao.UserDAO;
import com.kunaal.stubMock.service.LoginService;

/**
 * @author Kunaal A Trehan
 *
 */
public class MockLoginServiceTest {
	
	private LoginService loginService;
	private UserDAO mockUserDAO;
	
	@Before
	public void setup(){
		loginService=new LoginService();
		mockUserDAO=createMock(UserDAO.class);
		loginService.setUserDAO(mockUserDAO);
	}
	
	@Test
	public void authenticate(){
		//push the expectations and other information
		// Set expectations on mocks.
		expect(mockUserDAO.authenticate("Kunaal","Password")).
			andReturn(true);
		// Set mocks into testing mode.
		replay(mockUserDAO);
		
		assertTrue(loginService.authenticate("Kunaal", "Password"));
		//assertFalse(loginService.authenticate("Kunaal", "Kunaal"));
		verify(mockUserDAO);
	}


}

Whats the difference between these two?
So final word whats the difference between these two.As per my understanding mock is generated at the run time and it helps to test the state as well as interaction behavior between two classes.This is not possible in stub implementation as there is no way to verify whether the particular method in the dependent class has been invoked by the test class or not.


However I can be wrong.Do let me know if my understanding is not right.

No comments:

Post a Comment