Issue
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?
Solution
If the test case you are running is the actual one in your post you are doing things wrong
- You are mixing JUnit4 and JUnit5, that won't work in a single class.
- The
@TestPropertySource
is for property files not yaml files - 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. - 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. - The
ObjectMapper
inside your test method isn't used, so why construct it. - The
@SpringBootTest
can figure out the application class itself. - 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());
}
}
Answered By - M. Deinum
Answer Checked By - Timothy Miller (JavaFixing Admin)