0

There is the spring-boot application that uses spring-aop. proxy-target-class is true. I'm trying to create a test for a service class. This service depends on a component class. I want to inject a mock into the service instead of the real component.

I found some similar questions:

I choose this answer to the last question, and I have tried to implement this approach. I chose it because it is not tied to the implementation details of the proxy classes and I can easily use a config class in other tests.

Below there is the example which simulates the real problem.

@org.aspectj.lang.annotation.Aspect
@org.springframework.stereotype.Component
public class Aspect {
    @Before("within(demo.Service)")
    public void someAdvice() {
        System.out.println("advice");
    }
}

@org.springframework.stereotype.Service
public class Service {
    @Autowired
    private Component component;

    public void action() {
        System.out.println(component.action());
    }
}

@org.springframework.stereotype.Component
public class Component {
    public String action() {
        return "real action";
    }
}

@SpringApplicationConfiguration
public class ServiceTest extends BaseTest {
    @Autowired
    Service service;

    @Test
    public void testAction() {
        service.action();
    }

    @Configuration
    public static class Config {
        @Mock Component mock;

        public Config() {
            MockitoAnnotations.initMocks(this);
        }

        @Bean
        public Component component() {
            Mockito.when(mock.action()).thenReturn("mock action");
            return mock;
        }
    }
}

Complete example: https://github.com/eds0404/spring-inject-mock-into-proxy

The above code is not working as I expect, the service does not use mock ("real action" will be printed if you run test). But the above code works fine if the Component class is not marked with @Component annotation, and its objects are created by the method with @Been annotation.

How to solve this issue? If this is wrong approach, what is best practice?

Community
  • 1
  • 1
Dmitry
  • 291
  • 2
  • 6
  • 19
  • Is that supposed to be a unit-test? If so, you should use Spring at all to create your service. – JB Nizet Jun 06 '15 at 21:44
  • @JBNizet What do you mean? Yes, ServiceTest is a junit test. I use Autowired to create an object of the Service class. – Dmitry Jun 07 '15 at 10:20
  • If it's a unit test, and not an integration test, using new Service() is all you need to create the service. Dependencies should be mocked using classical Mockito techniques, and you shouldn't need any Spring context, configuration or anything. – JB Nizet Jun 07 '15 at 11:09
  • @JBNizet In the real application, the service depends on several components, I want to use mock instead of one of them. – Dmitry Jun 07 '15 at 13:43
  • 2
    So it's not a unit test. It's an integration test. You're testing the service with all its real dependencies (except one). – JB Nizet Jun 07 '15 at 13:44

0 Answers0