Mock classes with generic parameters using Mockito

May 04, 2022 No comments Mockito JUnit Java

1. Introduction

In this article, we will show how to Mock classes with generic parameters using Mockito.

2. Test class

The FooService will be our simple test class with generic parameters:

package com.frontbackend.libraries.mockito.service;

public class FooService<T> {

    private T obj;

    public T getValue() {
        return obj;
    }
}

The Car object will be used for parametrization of the FooService class:

package com.frontbackend.libraries.mockito.model;

public class Car {

    private final Driver driver;

    public Car(Driver driver) {
        this.driver = driver;
    }

    public String printWelcome() {
        return String.format("Welcome %s!", driver.getName());
    }
}

Driver class is an object injected into the Car instance:

package com.frontbackend.libraries.mockito.model;

public class Driver {

    private final String name;

    public Driver(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

3. Using casting

To mock class with generic parameter we could use Mockito mock method with casting.

package com.frontbackend.libraries.mockito;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.frontbackend.libraries.mockito.model.Car;
import com.frontbackend.libraries.mockito.model.Driver;
import com.frontbackend.libraries.mockito.service.FooService;
import org.junit.Test;

public class MockitoMockClassWithGenericParamTest {

    @Test
    public void shouldMockGenericService() {
        @SuppressWarnings("unchecked")
        FooService<Car> mockFoo = (FooService<Car>) mock(FooService.class);
        when(mockFoo.getValue()).thenReturn(new Car(new Driver("Mr Bean")));

        Car value = mockFoo.getValue();

        assertEquals("Welcome Mr Bean!", value.printWelcome());
    }
}

In this example, we used Mockito.mock(...) method to create a mock of FooService class. Then we cast it to the generic type FooService<Car>.

Note that there will be a warning:

Unchecked cast: 'com.frontbackend.libraries.mockito.service.FooService' to 'com.frontbackend.libraries.mockito.service.FooService<com.frontbackend.libraries.mockito.model.Car>'

but since it is just a JUnit class we could suppress this warning with the following annotation, and should not be worried about clean code that much:

@SuppressWarnings("unchecked")

4. Using @Mock annotation

The second way to mock a class with a generic parameter is to use @Mock annotation. This approach requires MockitoJUnitRunner:

package com.frontbackend.libraries.mockito;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

import com.frontbackend.libraries.mockito.model.Car;
import com.frontbackend.libraries.mockito.model.Driver;
import com.frontbackend.libraries.mockito.service.FooService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MockitoMockClassWithGenericParamUsingAnnotationTest {

    @Mock
    public FooService<Car> mockFoo;

    @Test
    public void testFoo() {
        when(mockFoo.getValue()).thenReturn(new Car(new Driver("Mr Bean")));

        Car value = mockFoo.getValue();

        assertEquals("Welcome Mr Bean!", value.printWelcome());
    }
}

In this example code we used @Mock annotation to create a mock object of FooService class. There is no obstacle to use a generic parameter for this object.

5. Conclusion

In this article, we present how to mock classes with generic parameters using Mockito.

As usual, code introduced in this article is available in our GitHub repository.

{{ message }}

{{ 'Comments are closed.' | trans }}