Home > Net >  How do I use spring @SpringBootTest instead of DataJPATest
How do I use spring @SpringBootTest instead of DataJPATest

Time:09-22

I have this code.

@RunWith(SpringRunner.class)
@SpringBootTest(
        webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT,
        classes = ApiDbApplication.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestPropertySource(
        locations = "classpath:application.yml")
@ExtendWith(SpringExtension.class)
@Transactional
public class LocationIT {

    @MockBean
    CompanyRepository companyRepository;
    @MockBean
    ShipmentRepository shipmentRepository;
    @MockBean
    ContactRepository contactRepository;

    private LocationController locationController;
    private LocationService locationService;

    @Autowired
    LocationRepository locationRepository;

    @LocalServerPort
    private int port;
    TestRestTemplate restTemplate = new TestRestTemplate();
    HttpHeaders headers = new HttpHeaders();

    @Before
    public void setup() {
        locationService = new LocationService(locationRepository);
        this.locationController = new LocationController(locationService);
    }



    @Test
    public void testAddLocation() {
        ObjectMapper mapper = new ObjectMapper()
                .registerModule(new JavaTimeModule());
        ;
        Location location = Location.builder()
                .id(Long.valueOf(7))
                .city("Fayetteville")
                .lat(32.33)
                .lon(37.49)
                .name("Big place")
                .State("Arkansas").build();

        ResponseEntity<String> responseEntity = this.restTemplate
                .postForEntity("http://localhost:"   port   "/api/location/save", location, String.class);

        ResponseEntity<List<Location>> results = restTemplate.exchange("http://localhost:"   port   "/api/location/list",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Location>>(){});


        assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
        assertEquals(HttpStatus.OK, results.getStatusCode());
        assertEquals(Collections.singletonList(location), results.getBody());

    }
}

Whenever I run the test. My location repository is null and I have the @Repository annotation. This is the error I get: No qualifying bean of type 'com.example.apidb.location.LocationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

I want to hit the endpoint using restTemplate, so I would rather not use @DataJPATest.

This question is similar: How can I use @SpringBootTest(webEnvironment) with @DataJpaTest?

CodePudding user response:

If the test case you are running is the actual one in your post you are doing things wrong

  1. You are mixing JUnit4 and JUnit5, that won't work in a single class.
  2. The @TestPropertySource is for property files not yaml files
  3. You should autowire the TestRestTemplate not create it (this also allows you to remove the @LocalServerPort as that is setup already as a base URL.
  4. Your @Before doesn't really make sense, constructing the service and controller don't add anything in your test, it only takes up memory and execution time.
  5. The ObjectMapper inside your test method isn't used, so why construct it.
  6. The @SpringBootTest can figure out the application class itself.
  7. The @AutoConfigureTestDatabase isn't needed, that is only for sliced tests like @DataJpaTest, @DataJdbcTest etc.

That all being said I would expect something like the following to work

Assuming you configured a proper datasource in your application.yml in your src/test/resources.


import org.junit.jupiter.api.Test

@SpringBootTest(
        webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT,
        )
class LocationIT {

    @MockBean
    private CompanyRepository companyRepository;
    @MockBean
    private ShipmentRepository shipmentRepository;
    @MockBean
    private ContactRepository contactRepository;
    
    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void testAddLocation() {       
        Location location = Location.builder()
                .id(Long.valueOf(7))
                .city("Fayetteville")
                .lat(32.33)
                .lon(37.49)
                .name("Big place")
                .State("Arkansas").build();

        ResponseEntity<String> responseEntity = this.restTemplate
                .postForEntity("/api/location/save", location, String.class);

        ResponseEntity<List<Location>> results = restTemplate.exchange("/api/location/list",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Location>>(){});

        assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
        assertEquals(HttpStatus.OK, results.getStatusCode());
        assertEquals(Collections.singletonList(location), results.getBody());
    }
}

CodePudding user response:

Johhnyutts answered the question. The answer was to add @EnableJpaRepositories(basePackageClasses = { LocationRepository.class}

  • Related