Inject a mock with JUnit

Inject that Mock!

I want to show you a trick to inject mock in a class when you can't (or just hate) to add get/set methods to the code that is to be tested.

If you are familiar with testing, in particular with Java/JUnit, you already know that to test a class in isolation, the base requirement is creating mocks of the classes that "collaborate" with the class you want to test, and inject the created mocks in it.

For example in this simple case:

package org.sample;
 
public class Client {
     
    private Service simpleService;
     
    public Client() {
        simpleService = new Service();
    }
     
    public String hello() {
        return simpleService.sayHello("Daniele");
    }
 
}
package org.sample;
 
public class Service {
 
    public String sayHello(String name) {
        return "Hello " + name;
    }
 
}

I want to test the class org.sample.Client mocking the simpleService instance of the class org.sample.Service. One of the things I can do to inject the mock of the Service class is adding a 'set' method to the Client class, like this:

public void setService (Service service) {
	this.simpleService = service;
}

Sometimes you can't (it's happened to me working for some companies :)) or maybe you just don't want to add this kind of method to the application code. So, how can I test in isolation without it? In my test-tool-box I added this "utils" class:

package org.sample;
 
import java.lang.reflect.Field;
 
public class ReflectionUtils {
 
    public static Object getField(Object o, String fieldName) {
        Field field = getAccessibleField(fieldName, o.getClass());
        Object fieldValue = null;
        try {
            fieldValue = field.get(o);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return fieldValue;
    }
 
    public static void setField(Object o, String fieldName, Object inject) {
        Field field = getAccessibleField(fieldName, o.getClass());
        try {
            field.set(o, inject);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
 
    // search in class, in case superclasses as well
    private static Field getAccessibleField(String fieldName, Class c) {
        Field field = null;
        while (c != null) {
            try {
                field = c.getDeclaredField(fieldName);
                field.setAccessible(true);
                break;
            } catch (NoSuchFieldException e) {
                c = c.getSuperclass();
            }
        }
        return field;
    }
}

Using it, we will get this test class:

package org.sample;
 
import static org.junit.Assert.*;
 
import org.junit.Before;
import org.junit.Test;
 
public class ClientTest {
     
    private Client client;
     
    @Before
    public void setUpMyStuff() {
        client = new Client();
        Service mock = new ServiceMock();
	// in place of client.setService(mock); we have:
        ReflectionUtils.setField(client, "simpleService", mock);
    }
 
    @Test
    public void hello() {
        assertEquals("Goodbye Daniele", client.hello());
    }
 
    // you can use something like Mockito to create a mock
    private class ServiceMock extends Service {
        @Override
        public String sayHello(String name) {
            return "Goodbye " + name;
        }
    }
}

In this test the "Service" class is mocked and the mock replaces the message "Hello Daniele" with "Goodbye Daniele". To inject the mock I've used:

public static void setField(Object o, String fieldName, Object inject)

in the ReflectionUtils class. Respectively the 3 parameters passed in the method are:

  • The instance of the class to test (or the class that needs a mock)
  • The name of the property inside the class that represents the class to mock
  • The mock instance

Try to run the test above un/commenting the line of code:

ReflectionUtils.setField(client, "simpleService", mock);

Enjoy!

More by this Author

  • How To Parse Html In Java - Part 2
    0

    In the first article we saw how to parse html in Java using the libraries: Jsoup HtmlCleaner Internal Swing SDK parser This time we will see other useful libraries to parse html like: TagSoup HTML Parser...

  • How to Create a Chat Room in Java
    0

    A quick and easy way to build your free and personal chat room in Java.

  • How To Parse Html In Java
    7

    Examples and information about how to parse html in Java using: Jsoup, HtmlCleaner, Internal Swing SDK parser, TagSoup, HTML Parser, JTidy, NekoHtml, Cobra, HotSAX and Jerico HTML Parser.


Comments 2 comments

NitroD profile image

NitroD 3 years ago from London Author

Glad it helped you :)


jchacana 3 years ago

Man, you saved my day. I was unable to use Arquillian with this legacy code but your snippet made it possible to inject dependencies. Thank you!

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working