Mock object method call using Spring Boot and Mockito

19,191

After a lot of trial and error I managed to solve this problem.

I dropped the

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ProductCompositeServiceApplication.class)

annotations aboved the test class.

I marked the class that I was testing with @InjectMocks and the dependencies with @Mock:

public class ProductCompositeIntegrationTest {
    @InjectMocks
    private ProductCompositeIntegration productIntegration;

    @Mock
    private ServiceUtils util;

    private MockRestServiceServer mockServer;

    private RestTemplate restTemplate = new RestTemplate();

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
        mockServer = MockRestServiceServer.createServer(restTemplate);
        productIntegration.setRestTemplate(restTemplate);
    }

    @Test
    public void someTests() {
        when(util.getServiceUrl("product")).thenReturn(URI.create("http://localhost:8080/test"));
        //Test code...
    }
}

I'm not sure if this is the best approach ("the Spring way"), but this worked for me.

This article made it all clear to me: http://rdafbn.blogspot.be/2014/01/testing-spring-components-with-mockito.html

Share:
19,191
Kaj
Author by

Kaj

Updated on July 25, 2022

Comments

  • Kaj
    Kaj over 1 year

    I am trying to write a test for this Java SpringBoot's class:

    https://github.com/callistaenterprise/blog-microservices/blob/master/microservices/composite/product-composite-service/src/main/java/se/callista/microservices/composite/product/service/ProductCompositeIntegration.java

    Specifically, I am trying to "mock" this method call:

    URI uri = util.getServiceUrl("product");
    

    I figured out I should "mock" the ServiceUtils object in order to do this. I tried this using the @Mock and @InjectMocks annotations:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = ProductCompositeServiceApplication.class)
    public class ProductCompositeIntegrationTest {
    
        @InjectMocks
        @Autowired
        private ProductCompositeIntegration productIntegration;
    
        @Autowired
        private RestTemplate restTemplate;
    
        @Mock
        private ServiceUtils util;
    
        private MockRestServiceServer mockServer;
    
        @Before
        public void setUp() {
            MockitoAnnotations.initMocks(this);
            mockServer = MockRestServiceServer.createServer(restTemplate);
        }
    
        @Test
        public void myTest() {
            Mockito.when(util.getServiceUrl("product")).thenReturn(URI.create("http://localhost:8080/test"));
            ResponseEntity<Iterable<Product>> products = productIntegration.getAllProducts();
        }
    }
    

    But this way it still calls the original ServiceUtils object, and not the "mocked" one. Also tried without the @Autowired annotation at the ProductCompositeIntegration, but this results in a NullPointerException.

    What am I doing wrong?


    My main class looks like this:

    @SpringBootApplication
    @EnableCircuitBreaker
    @EnableDiscoveryClient
    public class ProductCompositeServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(ProductCompositeServiceApplication.class, args);
        }
    }
    

    The ServiceUtils object that I am trying to mock is specified in a class, annotated with Spring's @Component annotation to inject it into the other classes using @Autowired.

  • Kaj
    Kaj over 8 years
    Do I have to change anything to the class that has to be tested? I tried to instantiate the ServiceUtils object in the Test class using this factory but the result is the same @Mock private ServiceUtils util = factoryBean.getObject();
  • Sandra Parsick
    Sandra Parsick over 8 years
    You have to add the FactoryBean in your test-context.xml. I edited the answer.
  • user2957378
    user2957378 about 8 years
    I liked your approach. It was exactly what I was looking for.