title: Spring Boot Integration Testing with mocked Services/Components
body: <p><strong>Situation and Problem</strong>: In Spring Boot, how can I inject one or more mocked classes/beans into the application to do an integration test? There are a few answers on StackOverflow, but they are focused on the situation before Spring Boot 1.4 or are just not working for me.</p>
  
  <p>The background is, that in the code bellow the implementation of Settings relies on third party servers and other external systems. The functionality of Settings is already tested in a unit test, so for a full integration test I want to mock out the dependency to these servers or system and just provide dummy values.</p>
  
  <p>MockBean will ignore all existing bean definitions and provide a dummy object, but this object doesn't provide a method behavior in other classes that inject this class. Using the @Before way to set the behavior before a test doesn't influence the injected object or isn't injected in other application services like AuthenticationService.</p>
  
  <p><strong>My question</strong>: How can I inject my beans into the application context? 
  My test:</p>
  
  <pre><code>package ch.swaechter.testapp;
  
  import ch.swaechter.testapp.utils.settings.Settings;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.mockito.Mockito;
  import org.springframework.boot.test.context.SpringBootTest;
  import org.springframework.boot.test.mock.mockito.MockBean;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Primary;
  import org.springframework.test.context.junit4.SpringRunner;
  
  @TestConfiguration
  @RunWith(SpringRunner.class)
  @SpringBootTest(classes = {MyApplication.class})
  public class MyApplicationTests {
  
      @MockBean
      private Settings settings;
  
      @Before
      public void before() {
          Mockito.when(settings.getApplicationSecret()).thenReturn("Application Secret");
      }
  
      @Test
      public void contextLoads() {
          String applicationsecret = settings.getApplicationSecret();
          System.out.println("Application secret: " + applicationsecret);
      }
  }
  </code></pre>
  
  <p>And bellow a service that should use the mocked class, but doesn't receive this mocked class:</p>
  
  <pre><code>package ch.swaechter.testapp;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Service;
  
  @Service
  public class AuthenticationServiceImpl implements AuthenticationService {
  
      private final Settings settings;
  
      @Autowired
      public AuthenticationServiceImpl(Settings settings) {
          this.settings = settings;
      }
  
      @Override
      public boolean loginUser(String token) {
          // Use the application secret to check the token signature
          // But here settings.getApplicationSecret() will return null (Instead of Application Secret as specified in the mock)!
          return false;
      }
  }
  </code></pre>