Joy
Joy

Reputation: 4473

Writing unit test for Map injection in Guice

I am new to Guice. I have written following class that depends on generic map which is managerMap that maps object type to specific manager responsible for handling that type of object.

public class MyClass<T extends MyClass> {

    @Inject
    @Named("ManagerMap")
    private Map<String, Manager> managerMap;

    @Override
    public void myFunc(@NotNull T myObj) {
        Manager manager = managerMap.get(myObj.getClass().getName());
        manager.call(myObj);
    }
}

Above code is running fine. Now I would like to write unit test for above. I have written like following, it is working, but I think there is a better way to do that.

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

    @InjectMocks
    private MyClass myclass;

    @Mock
    private Map<String, Manager> managerMap;

    private final MyClass1 myObj;     <--MyClass1 extends from MyClass

    @Test
    public void testmyFunc() {
        Mockito.when(managerMap.get(myObj.getClass().getName())).thenReturn(new MyManager1());
        myclass.myFunc(myObj);
    }
}

Upvotes: 3

Views: 815

Answers (1)

tkruse
tkruse

Reputation: 10685

Which is the "best" way to do things is a matter of taste, so not a good question for SO.

But this is how I would write that code:

public class MyClass<T extends MyClass> {

    private final Map<String, Manager> managerMap;

    @Inject // constructor injection
    @Named("ManagerMap")
    public class Myclass(Map<String, Manager> managerMap) {
        this.managerMap = managerMap;
    }

    @Override
    public void myFunc(@NotNull T myObj) {
        Manager manager = managerMap.get(myObj.getClass().getName());
        manager.call(myObj);
    }
}

Test

public class MyClassTest {

    private MyClass myclass;

    @Test
    public void testmyFunc() {
        // prepare map
        Map<String, Manager> managerMap = new HashMap();
        MyManager1 = myManager new MyManager1()
        managerMap.put(myObj.getClass.getName(), myManager);

        // create class under test with injected map
        myclass = new MyClass(managerMap);

        myclass.myFunc(myManager);
    }
}

So by using Constructor injection and a normal HashMap, the test code becomes much cleaner, and the class under test is not much worse. Mockito is not needed here.

If you do want to pass in a Manager Mock, you'll likely need Powermock such as in this question to mock the getClass() call.

Upvotes: 1

Related Questions