0

I'm new to testing and am currently testing services and controllers in the spring application.

When I started doing integration tests in the service layer, I posted an annotation

@SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)   

and always got an error:

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest (classes = ...) with your test

And then, as a solution, I set annotation like this:
@SpringBootTest (classes = MyApplication.class) and everything worked ok.

However now that I have started testing the controller layer and I need a TestRestTemplate:

@Autowired
private TestRestTemplate restTemplate;

I get the error :

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.ftn.controllers.AddressControllerTest': Unsatisfied dependency expressed through field 'restTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.test.web.client.TestRestTemplate' available: expected at least 1 bean which qualifies as an autowire candidate. Dependency annotations: {@ org.springframework.beans.factory.annotation.Autowired (required = true)}

My test class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TicketServiceApplication.class)
@Transactional
@TestPropertySource("classpath:application-test.properties")
public class AddressControllerTest {

    @Autowired
    private AddressRepository addressRepository;

    @Autowired
    private TestRestTemplate restTemplate;

    private String accessToken;

    private HttpHeaders headers = new HttpHeaders();

    @Before
    public void login() {
        ResponseEntity<LoggedInUserDTO> login = restTemplate.postForEntity("/login",  new LoginDTO("admin", "admin"), LoggedInUserDTO.class);
        accessToken = login.getBody().getToken();
        headers.add("Authorization", "Bearer "+accessToken);
    }

    @Test
    public void testGetAllAddresses() {
        ResponseEntity<AddressDto[]> responseEntity = restTemplate.getForEntity("/api/address", AddressDto[].class);
        AddressDto[] addressesDto = responseEntity.getBody();
        AddressDto a1 = addressesDto[1];


        assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
        assertNotNull(addressesDto);
        assertNotEquals(0, addressesDto.length);
        assertEquals(2, addressesDto.length);
        assertEquals(AddressConst.DB_STATE, a1.getState());
        assertEquals(AddressConst.DB_CITY, a1.getCity());
        assertEquals(AddressConst.DB_STREET, a1.getStreet());
        assertEquals(AddressConst.DB_NUM, a1.getNumber());
    }
}

What is the right solution and what is the right way to do the integration tests properly?
Why makes me a problem to use webEnvironment in SpringBootTest?

EDIT: Now when I remove @RunWith() anotation, TestRestTemlpate is null and I have NullPointerException in first line of test where I try to get response object.

If anyone can help and explain a little bit about this, I'm sorry but I'm new to spring testing. Thank you!

jovanKg
  • 35
  • 7
  • From the documentation for [TestRestTemplate](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/web/client/TestRestTemplate.html) , *If you are using the @SpringBootTest annotation, a TestRestTemplate is automatically available and can be @Autowired into your test* . Have you annotated the test class with `@SpringBootTest` ?Could you please share the complete test class ? – R.G Mar 25 '20 at 04:04
  • That I also read the documentation and that's why it makes no sense to me. And yes I put an annotation above class. I edited the question where I added my test class. – jovanKg Mar 25 '20 at 11:58
  • 1
    Could you please try removing the `@RunWith` annotation and try . [`@SpringBootTest`](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/context/SpringBootTest.html) is already meta annotated with `@ExtendWith` . Read more on this [here](https://stackoverflow.com/a/55281655/4214241) – R.G Mar 25 '20 at 13:50
  • This solved my problem, thank you! What's the point now, is I didn't need to use @RunWith() anywhere or I needed to? But now without @RunWith() I think when I run the test it does not load spring context. – jovanKg Mar 25 '20 at 15:07
  • You don't have to as `@SpringBootTest` already does that for you with `@ExtendWith` which is for Junit 5 and above. Shall I convert this comment to answer to close the question ? – R.G Mar 25 '20 at 15:08
  • Just to mention that I had to put @Autowired private TestRestTemplate restTemplate = new TestRestTemplate(); to get in test because it was throwing NullPointerException when try to get response object. – jovanKg Mar 25 '20 at 15:37
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/210316/discussion-between-jovankg-and-r-g). – jovanKg Mar 25 '20 at 15:38

0 Answers0