Search code examples
javajunitmockingmockito

Can multiple mocks of a class be used in a single test class?


I have a class:

classA
{
    private Boolean isEnable;

    private final Config config;

    public classA(final Config config)
    {
        this.config = config;
        isEnable = config.getEnablingStatus();
    }

    public classB fun()
    {
        // Do something!
        // Return an object of classB!
    }
}

I want to test the method fun() in 2 different scenarios - one in which isEnable is true, and one in which it's false.

So, to do that I am thinking of having 2 different instances of the classA in its test class:

TestClassForClassA
{
    private Boolean isEnable;
    
    @Mock
    private final Config config;
   
    @InjectMocks
    classA objAWithIsEnableAsTrue, objAWithIsEnableAsFalse;

    @Before
    public void init() 
    {
        initMocks(this);
    }

    public void testFunWhenIsEnableIsTrue()
    {
        doReturn(true).when(config).getEnablingStatus();
        objAWithIsEnableAsTrue = new classA(config);
        // Use the objAWithIsEnableAsTrue object in this test method.
    }

    public void testFunWhenIsEnableIsFalse()
    {
        doReturn(false).when(config).getEnableStatus();
        objAWithIsEnableAsFalse = new classA(config);
        // Use the objAWithIsEnableAsFalse object in this test method.
    }
}

Can it be done like this? If not what is the right way to do it?


Solution

  • This is not the answer to the question you wrote but I guess it could be the answer you need:

    From the code you posted there is no reason to mock classA. In the @Before annotated method you even instantiate the objects by calling the constructor. This means those objects (objAWithIsEnableAsTrue and objAWithIsEnableAsFalse) are not even mocked in your tests.


    In order to make your tests more clear, I would suggest moving the setup logic of your tests into the test methods themselves.

    TestClassForClassA {
    
        @Test
        public void testFunWhenIsEnableIsTrue(){
            Config config = mock(Config.class);
            doReturn(true).when(config).getEnableStatus();
    
            classA objAWithIsEnableAsTrue = new classA(config);
            // Use the objAWithIsEnableAsTrue object in this test method.
        }
    
        @Test
        public void testFunWhenIsEnableIsFalse(){
            Config config = mock(Config.class);
            doReturn(false).when(config).getEnableStatus();
    
            classA objAWithIsEnableAsfalse = new classA(config);
            // Use the objAWithIsEnableAsTrue object in this test method.
        }
    }
    

    Also, you should check if you really need to mock the Config object. Can it also be instantiated without side effects? If yes, I would do so to get rid of the whole mocking.

    Config config = new Config(); 
    config.setEnablingStatus(true); // maybe do this instead of mocking?