I can't understand why @Autowiring my @RestController class is returning null. I want to do a basic unit test before doing an integrated test but its failing. In fact anything that is being @Autowired is showing null in the test package.
I have a very simple test, I just want to see the basic works:
A very simple example:
@Component
public class SimpleComponent {
public int add(int a, int b){
return a b;
}
}
And the test:
class SimpleComponentTest {
@Autowired
private SimpleComponent component;
@Test
public void givenSimpleComponentShouldNotBeNull(){
assertNotNull(component);//How on earth does this fail?
}
}
Here is the code from the Controller class:
@RestController
public class EmployeeAccountApi {
@PostMapping("/register")
public String register(){
return "Registering!";
}
}
public class EmployeeAccountApiUnitTest {
@Autowired
private EmployeeAccountApi employeeAccountApi;
@Test
public void testAutowiring(){
assertNotNull(employeeAccountApi);//Fails, Can't understand why
}
}
This works with the @Mock annotation: But I dont want to mock it as that is the class I am unit testing. I want to test that the method returns a basic string. Question is why isn't it working?
@ExtendWith(MockitoExtension.class)
public class EmployeeAccountApiUnitTest {
@Mock
private EmployeeAccountApi employeeAccountApi;
@Test
public void testAutowiring(){
assertNotNull(employeeAccountApi);//This works
}
}
Even if I get the Employee Service that clearly worked and tested in the previous test also is null in this class:
public class EmployeeAccountApiUnitTest {
@Autowired
private EmployeeAccountApi employeeAccountApi;
@Autowired
private EmployeeService service;
@Test
public void testAutowiring(){
//assertNotNull(employeeAccountApi);
assertNotNull(service);
}
}
Why is @Autowired null in the Test? Mocking is working fine
Plenty of similar questions but they are too specific and not provide any basic information
CodePudding user response:
@Autowired only works if you are spinning up the application context for your application. Annotate the test class with @SpringBootTest
, which tells the test to start the entire spring application context, and it should work.
CodePudding user response:
@SpringBootTest has to be used on the test class for Spring to load your ApplicationContext and wire things up. Without out this there's nothing for Spring to inject.
You can use @WebMvcTest on the test class to focus your tests only on the Web Layer.
There's a whole bunch of annotations that allow you to "slice" your ApplicationContext up lots of other ways for testing various other parts of your application.
Spring's documentation and tutorials are really very good. You should check them out.