Showing posts with label Mocking. Show all posts
Showing posts with label Mocking. Show all posts

Tuesday, August 05, 2014

Mocking the InitialContext

Unit testing with JNDI

One of the issue's with unit tests is that it is not always easy to control the java.naming.InitialContext provided to the object under test.
Mock frameworks cannot create mocks for JRE classes like InitialContext, so how can we solve this challenge?

One solution could be to create a simple implementation for the javax.naming.spi.InitialContextFactory that returns a mock implementation provided by mockito. Through configuration, our implementation is then used.

public class InitialContextFactoryMock implements InitialContextFactory {

  private static Context mockContext;

  /**
    * The mockContext is created here to be able to use the {@link Context}
    * mock object while defining the expectations.
    * Remember to call this method each time a new test case is run.
    * 
    * @return a fresh {@link Context} mock.
    */
  public static Context getMockContext() {
    mockContext = mock(Context.class);

    return mockContext;
  }

  /**
    * This factory returns the {@link Context} mock created earlier.
    */
  public Context getInitialContext(Hashtable environment) throws NamingException {
    return mockContext;
  }
}

To use the InitialContextFactoryMock you need to specify it in the jndi.properties:


java.naming.factory.initial=the.mocks.InitialContextFactoryMock

Wednesday, February 02, 2011

Create mock objects in spring configuration

In case you ever need to supply a mock object in spring configuration, here's a snippet that does just that:

<!-- Define the Mockito class as factory for creating the mock -->
<bean id="restTemplate" class="org.mockito.Mockito" factory-method="mock">
  <!-- The constructor contains the full name of the class being mocked -->
  <constructor-arg value="org.springframework.web.client.RestTemplate"/>
</bean>


The defined restTemplate bean can be be referenced in other bean definitions, for instance the object under test.

Wednesday, August 11, 2010

How to test a class that directly uses java.rmi.Naming

While in the process of doing a handover of a project, some pieces of the projects source do not comply with the code standard. In this holiday season the original developer wasn't available, so I made my sleeves wet and hands dirty again, and started fixing it.

The major thing the code lacked was a proper unit test with coverage higher than 80%, well it didn't have a unit test at all.
Adding a unit test normally is not a big deal, but in this case, the class, a simple servlet that connects to a remote RMI object and calls a status method on it, directly uses java.rmi.Naming.
java.rmi.Naming is notorious for its static methods, which are hard to mock when unit testing.
There are great products out there, like powermock that can actually mock static methods, but not in system classes.
I could change the servlet code and provide a wrapper around accessing the java.rmi.Naming class, but I didn't want to change the code.

Instead I chose to not mock java.rmi.Naming, but instead just create my own instance:
@BeforeClass
public static void initNamingRegistry() throws RemoteException {
// Create a local registry with an arbitrary port number
rmiRegistry = LocateRegistry.createRegistry(9901);
This registry is alive and kickin' during the execution of my test suite, so I can now register the mock object that implements the remote business interface:
@Before
public void registerRemoteMock() throws Exception {
// Register the mock of the remote business object
rmiRegistry.bind("testName", remoteMock);
}
Then the actual servlet method can bet tested:
@Test
public void testSomeBehaviour()
// Prepare the mocks
when(requestMock.getParameter("name").thenReturn("val");
...
// Call the test method
testObject.doGet(requestMock, responseMock);

// Verify the calls if needed
verify(remoteMock).doIt();
Nice, clean and simple!