title: Spring - How to properly use @Autowired to prevent controller / MockMvc from being null?
body: <p>I'm attempting to run some unit tests and encountering an issue that I am sure stems from a misunderstanding about autowiring.  I have a unit test class in which I am trying to use <code>@Autowired</code> on a MockMvc and a REST controller -- both of which end up being null.</p>
  
  <p>I have seen some sources try to explain why this can happen (including this <a href="https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/" rel="nofollow noreferrer">More of Less post</a> and a helpful <a href="https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null">StackOverflow post</a> that has given me some insight but hasn't completely helped me solve my problem).</p>
  
  <p>Below is relevant source code from a sample project I've made to recreate this problem.</p>
  
  <p><strong>ManagerControllerTest.java</strong></p>
  
  <pre><code>@RunWith(SpringRunner.class)
  @WebMvcTest(ManagerController.class)
  public class ManagerControllerTest {
      @Autowired
      private MockMvc mockMvc;
  
      @MockBean
      private Manager manager;
  
      @Autowired
      private ManagerController controller;
  
      @Test
      public void controllerNotNull() throws Exception {
          assertThat(controller).isNotNull();
      }
  
      @Test
      public void testStoreSomething() throws Exception {
          String path = "/manager/store-something/";
  
          MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(path)
                      .characterEncoding("UTF-8")
                      .contentType(MediaType.APPLICATION_JSON);
  
          MvcResult result = mockMvc.perform(builder).andReturn();
          assertEquals(HttpStatus.CREATED, result.getResponse().getStatus());
      }
  }
  </code></pre>
  
  <p>The <code>controllerNotNull()</code> test results in</p>
  
  <blockquote>
    <p>java.lang.AssertionError:  Expecting actual not to be null</p>
  </blockquote>
  
  <p>Although, curiously, when I created a new Gradle project in Java and imported my sample code from this post into it, <code>controllerNotNull()</code> passes.</p>
  
  <p>And <code>testStoreSomething()</code> results in</p>
  
  <blockquote>
    <p>java.lang.NullPointerException    at
    com.example.sandbox.rest.ManagerControllerTest.testStoreSomething(ManagerControllerTest.java:46)</p>
  </blockquote>
  
  <p>And here in lies the question: What am I misunderstanding?  What am I doing wrong? I can remove the <code>@Autowired</code> from the controller and just instantiate it with <code>new ManagerController()</code> but I am left with MockMvc issue.</p>
  
  <p><strong>ManagerController.java</strong></p>
  
  <pre><code>@Controller
  @RequestMapping(value = "/manager/")
  public class ManagerController {
      Manager manager = new Manager(new StringStorage());
  
      @PostMapping(value = "store-something")
      private ResponseEntity&lt;?&gt; storeSomething(String str) {
          manager.storeSomething(str);
          return new ResponseEntity&lt;&gt;(CREATED);
      }
  }
  </code></pre>
  
  <p><strong>Manager.java</strong></p>
  
  <pre><code>public class Manager {
      private final Storage storage;
  
      public Manager(Storage storage) {
          this.storage = storage;
      }
  
      public void storeSomething(String str) {
          storage.store(str);
      }
  }
  </code></pre>
  
  <p><strong>Storage.java</strong></p>
  
  <pre><code>public interface Storage {
      void store(String str);
  }
  </code></pre>
  
  <p><strong>StringStorage.java</strong></p>
  
  <pre><code>public class StringStorage implements Storage {
      Map&lt;String, String&gt; stringMap;
  
      @Override
      public void store(String str) {
          stringMap.put(str, str);
      }
   }
  </code></pre>
  
  <p><strong>Application.java</strong></p>
  
  <pre><code>@SpringBootApplication
  public class Application {
  
      public static void main(String[] args) {
          SpringApplication.run(Application.class, args);
      }
  
  }
  </code></pre>
  
  <p><strong>build.gradle</strong> Which has been edited from the original post (to use JUnit4) but the problem remains.</p>
  
  <pre><code>repositories {
      jcenter()
  }
  
  apply plugin: 'java'
  apply plugin: 'eclipse'
  
  dependencies {
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE'
      compile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '2.0.0.RELEASE'
  
      testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE'
      testImplementation 'org.junit.jupiter:junit-jupiter-api:4.0.0'
      testImplementation 'org.junit.jupiter:junit-jupiter-params:4.0.0'
      testCompile group: 'org.mockito', name: 'mockito-core', version: '2.17.0'
      testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: "4.0.0"
      testCompile group: 'org.junit.platform', name: 'junit-platform-launcher', version: "1.3.1"
  }
  </code></pre>