Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • xgulcik/pa165-formula-one-team
1 result
Show changes
Showing
with 770 additions and 76 deletions
package cz.muni.pa165.common_library.exception; package cz.muni.pa165.common_library.exception;
import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.EntityNotFoundException;
import org.apache.hc.client5.http.HttpHostConnectException;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
...@@ -11,6 +12,7 @@ import org.springframework.web.bind.MethodArgumentNotValidException; ...@@ -11,6 +12,7 @@ import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.NoHandlerFoundException;
/** /**
...@@ -88,7 +90,7 @@ public class RestExceptionHandler { ...@@ -88,7 +90,7 @@ public class RestExceptionHandler {
for (ObjectError error : validationErrors) { for (ObjectError error : validationErrors) {
var errorField = (FieldError) error; var errorField = (FieldError) error;
var errorMessage = errorField.getDefaultMessage(); var errorMessage = errorField.getDefaultMessage();
var fieldName = errorField.getField(); var fieldName = errorField.getField();
validtionMessage.append(" field ").append(fieldName).append(": ") validtionMessage.append(" field ").append(fieldName).append(": ")
.append(errorMessage).append(","); .append(errorMessage).append(",");
...@@ -102,4 +104,47 @@ public class RestExceptionHandler { ...@@ -102,4 +104,47 @@ public class RestExceptionHandler {
return new ResponseEntity<>( return new ResponseEntity<>(
new ExError(message), new HttpHeaders(), HttpStatus.BAD_REQUEST); new ExError(message), new HttpHeaders(), HttpStatus.BAD_REQUEST);
} }
/**
* Handler for server error exception.
*
* @param ex thrown exception.
* @return Message with datetime.
*/
@ExceptionHandler(HttpServerErrorException.class)
public ResponseEntity<ExError> handleServerException(HttpServerErrorException ex) {
return new ResponseEntity<>(
new ExError(ex.getMessage()), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
/**
* Handler for server error exception.
*
* @param ex thrown exception.
* @return Message with datetime.
*/
@ExceptionHandler(HttpServerErrorException.InternalServerError.class)
public ResponseEntity<ExError> handleServerException(
HttpServerErrorException.InternalServerError ex) {
return new ResponseEntity<>(
new ExError(ex.getMessage()), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
/**
* Handler for server error exception.
*
* @param ex thrown exception.
* @return Message with datetime.
*/
@ExceptionHandler(HttpHostConnectException.class)
public ResponseEntity<ExError> handleServerException(HttpHostConnectException ex) {
var message = "";
if (ex.getMessage().contains("8083")) {
message = "Failed to connect to the driver service";
} else if (ex.getMessage().contains("8082")) {
message = "Failed to connect to the car service";
}
return new ResponseEntity<>(
new ExError(message), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);
}
} }
...@@ -48,6 +48,12 @@ ...@@ -48,6 +48,12 @@
<artifactId>spring-data-jpa</artifactId> <artifactId>spring-data-jpa</artifactId>
<version>3.0.2</version> <version>3.0.2</version>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
......
package cz.muni.pa165.component; package cz.muni.pa165.component;
import cz.muni.pa165.common_library.exception.RestExceptionHandler; import jakarta.persistence.EntityManagerFactory;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.client.RestTemplate;
/** /**
* Main app. * Main app.
*/ */
@SpringBootApplication @SpringBootApplication()
@EnableJpaRepositories(basePackages = {"cz.muni.pa165.component.data.repository"})
@EntityScan("cz.muni.pa165.component.data.model") @EntityScan("cz.muni.pa165.component.data.model")
@Import(RestExceptionHandler.class)
public class App { public class App {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(App.class, args); SpringApplication.run(App.class, args);
} }
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
} }
package cz.muni.pa165.component.data.repository; package cz.muni.pa165.component.data.repository;
import cz.muni.pa165.component.data.model.CarComponent; import cz.muni.pa165.component.data.model.CarComponent;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
/** /**
...@@ -9,4 +13,11 @@ import org.springframework.stereotype.Repository; ...@@ -9,4 +13,11 @@ import org.springframework.stereotype.Repository;
*/ */
@Repository @Repository
public interface ComponentRepositoryInterface extends JpaRepository<CarComponent, Long> { public interface ComponentRepositoryInterface extends JpaRepository<CarComponent, Long> {
@Query("SELECT c FROM CarComponent c WHERE c.id = :id")
Optional<CarComponent> findById(@Param("id") Long id);
@Query("SELECT c FROM CarComponent c")
List<CarComponent> findAll();
} }
...@@ -8,6 +8,7 @@ import cz.muni.pa165.component.data.repository.ComponentRepositoryInterface; ...@@ -8,6 +8,7 @@ import cz.muni.pa165.component.data.repository.ComponentRepositoryInterface;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
...@@ -34,6 +35,7 @@ public class ComponentService implements ComponentServiceInterface { ...@@ -34,6 +35,7 @@ public class ComponentService implements ComponentServiceInterface {
* @param carComponentId id of the component. * @param carComponentId id of the component.
* @return found car component. * @return found car component.
*/ */
@Transactional(readOnly = true)
public CarComponentResponseDto getCarComponentById(Long carComponentId) { public CarComponentResponseDto getCarComponentById(Long carComponentId) {
return carComponentConverter(componentRepository.findById(carComponentId).orElseThrow( return carComponentConverter(componentRepository.findById(carComponentId).orElseThrow(
() -> new DatabaseException("Something went wrong when finding car component with id: " () -> new DatabaseException("Something went wrong when finding car component with id: "
...@@ -45,6 +47,7 @@ public class ComponentService implements ComponentServiceInterface { ...@@ -45,6 +47,7 @@ public class ComponentService implements ComponentServiceInterface {
* *
* @return list of stored car components. * @return list of stored car components.
*/ */
@Transactional(readOnly = true)
public List<CarComponentResponseDto> getAllCarComponents() { public List<CarComponentResponseDto> getAllCarComponents() {
return componentRepository.findAll() return componentRepository.findAll()
.stream() .stream()
...@@ -57,6 +60,7 @@ public class ComponentService implements ComponentServiceInterface { ...@@ -57,6 +60,7 @@ public class ComponentService implements ComponentServiceInterface {
* *
* @param carComponentId of the car component for removal. * @param carComponentId of the car component for removal.
*/ */
@Transactional
public String deleteById(Long carComponentId) { public String deleteById(Long carComponentId) {
componentRepository.deleteById(carComponentId); componentRepository.deleteById(carComponentId);
return "Car component with id: " + carComponentId + "was successfully deleted"; return "Car component with id: " + carComponentId + "was successfully deleted";
......
package cz.muni.pa165.component.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
/**
* Configuration for tests.
*/
@Configuration
public class TestConfig {
private DataSource dataSource;
@Autowired
public void setDataSource() {
this.dataSource = dataSource();
}
/**
* Data source for factory.
*
* @return data source
*/
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:component;DB_CLOSE_DELAY=-1");
dataSource.setUsername("admin");
dataSource.setPassword("admin");
return dataSource;
}
/**
* Custom entity manager factory.
*
* @return factory bean
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("cz.muni.pa165.component");
factory.setDataSource(dataSource);
return factory;
}
}
package cz.muni.pa165.component.repository;
import static cz.muni.pa165.component.util.ComponentTestUtil.getComponent;
import cz.muni.pa165.component.data.model.CarComponent;
import cz.muni.pa165.component.data.repository.ComponentRepositoryInterface;
import java.math.BigDecimal;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Unit tests for component repository.
*/
@RunWith(SpringRunner.class)
@DataJpaTest
public class ComponentRepositoryUnitTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private ComponentRepositoryInterface componentRepository;
@Test
public void saveTest() {
Long id = 1L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
var savedComponent = componentRepository.save(carComponent);
Assertions.assertEquals(savedComponent, carComponent);
Assertions.assertEquals(entityManager.find(CarComponent.class, 1L).getId(), 1);
}
@Test
public void findByIdTest() {
Long id = 2L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
var savedComponent = componentRepository.save(carComponent);
var component = componentRepository.findById(savedComponent.getId()).orElseThrow();
Assertions.assertAll(
() -> Assertions.assertEquals(component.getId(), savedComponent.getId()),
() -> Assertions.assertEquals(component.getName(), savedComponent.getName()),
() -> Assertions.assertEquals(component.getPrice(), savedComponent.getPrice()),
() -> Assertions.assertEquals(component.getWeight(), savedComponent.getWeight()),
() -> Assertions.assertEquals(component.getManufacturer(), savedComponent.getManufacturer())
);
}
@Test
public void findByNonExistingIdTest() {
Assertions.assertThrows(Exception.class, () -> componentRepository.findById(-1L).orElseThrow());
}
@Test
public void deleteByIdTest() {
Long id = 3L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
var savedComponent = componentRepository.save(carComponent);
componentRepository.delete(savedComponent);
Assertions.assertThrows(Exception.class, () -> componentRepository
.findById(savedComponent.getId()).orElseThrow());
}
@Test
public void testFindAll() {
Long id1 = 4L;
Long id2 = 5L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent1 = getComponent(id1, name, one, manufacturer);
var carComponent2 = getComponent(id2, name, one, manufacturer);
componentRepository.save(carComponent1);
componentRepository.save(carComponent2);
var components = componentRepository.findAll();
Assertions.assertEquals(2, components.size());
}
}
package cz.muni.pa165.component.rest;
import static cz.muni.pa165.component.util.ComponentTestUtil.getComponent;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.fasterxml.jackson.databind.ObjectMapper;
import cz.muni.pa165.component.data.model.CarComponent;
import cz.muni.pa165.component.data.repository.ComponentRepositoryInterface;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest
@AutoConfigureMockMvc
class ComponentControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ComponentRepositoryInterface componentRepositoryMock;
@Autowired
private ObjectMapper objectMapper;
@Test
void postIntegrationTest() throws Exception {
Long id = 1L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
given(componentRepositoryMock.save(any(CarComponent.class))).willReturn(carComponent);
String response = mockMvc.perform(post("/component/")
.content(objectMapper.writeValueAsString(carComponent))
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
CarComponent componentResponse = objectMapper.readValue(response, CarComponent.class);
assertAll(
() -> assertEquals(carComponent.getId(), componentResponse.getId()),
() -> assertEquals(carComponent.getName(), componentResponse.getName()),
() -> assertEquals(carComponent.getWeight(), componentResponse.getWeight()),
() -> assertEquals(carComponent.getPrice(), componentResponse.getPrice()),
() -> assertEquals(carComponent.getManufacturer(), componentResponse.getManufacturer())
);
}
@Test
void deleteIntegrationTest() throws Exception {
Long id = 1L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
given(componentRepositoryMock.findById(anyLong())).willReturn(
Optional.of(carComponent));
String expectedResponse = "Car component with id: 1was successfully deleted";
String actualResponse = mockMvc.perform(delete("/component/")
.param("componentId", String.valueOf(id))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
Assertions.assertEquals(expectedResponse, actualResponse);
}
@Test
void getComponentByIdTest() throws Exception {
Long id = 1L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
given(componentRepositoryMock.findById(id)).willReturn(Optional.of(carComponent));
String response = mockMvc.perform(get("/component/id")
.param("componentId", String.valueOf(id))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
var componentResponse = objectMapper.readValue(response, CarComponent.class);
Assertions.assertAll(
() -> Assertions.assertEquals(id, componentResponse.getId()),
() -> Assertions.assertEquals(name, componentResponse.getName()),
() -> Assertions.assertEquals(one, componentResponse.getWeight()),
() -> Assertions.assertEquals(one, componentResponse.getPrice()),
() -> Assertions.assertEquals(manufacturer, componentResponse.getManufacturer())
);
}
@Test
void getAllComponentsTest() throws Exception {
Long id = 1L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
given(componentRepositoryMock.findAll()).willReturn(List.of(carComponent));
String response = mockMvc.perform(get("/component/")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
var componentResponse = objectMapper.readValue(response, CarComponent[].class);
Assertions.assertAll(
() -> Assertions.assertEquals(id, componentResponse[0].getId()),
() -> Assertions.assertEquals(name, componentResponse[0].getName()),
() -> Assertions.assertEquals(one, componentResponse[0].getWeight()),
() -> Assertions.assertEquals(one, componentResponse[0].getPrice()),
() -> Assertions.assertEquals(manufacturer, componentResponse[0].getManufacturer())
);
}
}
package cz.muni.pa165.component.rest;
import static cz.muni.pa165.component.util.ComponentTestUtil.getComponent;
import static cz.muni.pa165.component.util.ComponentTestUtil.getComponentResponseDto;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.fasterxml.jackson.databind.ObjectMapper;
import cz.muni.pa165.common_library.dtos.CarComponentRequestDto;
import cz.muni.pa165.common_library.dtos.CarComponentResponseDto;
import cz.muni.pa165.component.data.model.CarComponent;
import cz.muni.pa165.component.service.ComponentService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@WebMvcTest(ComponentController.class)
class ComponentControllerUnitTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ComponentService componentService;
@Autowired
private ObjectMapper objectMapper;
@Test
void createCarComponentTest() throws Exception {
Long id = 1L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponent = getComponent(id, name, one, manufacturer);
var carComponentResponseDto = getComponentResponseDto(id, name, one, manufacturer);
given(componentService.postCarComponent(CarComponentRequestDto.builder().build()))
.willReturn(carComponentResponseDto);
mockMvc.perform(post("/component/")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(carComponent)))
.andExpect(status().isOk());
}
@Test
void nonExistingPathTest() throws Exception {
mockMvc.perform(post("/invalidPath"))
.andExpect(status().isNotFound());
}
@Test
void createComponentWithNullValuesTest() throws Exception {
CarComponent carComponent = new CarComponent();
CarComponentRequestDto carComponentRequestDto = new CarComponentRequestDto();
CarComponentResponseDto carComponentResponseDto = new CarComponentResponseDto();
given(componentService.postCarComponent(carComponentRequestDto))
.willReturn(carComponentResponseDto);
mockMvc.perform(post("/component/").contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(carComponent)))
.andExpect(status().isBadRequest());
}
@Test
void deleteCarComponentTest() throws Exception {
Long id = 1L;
String expectedResponse = "Car component with id: 1was successfully deleted";
given(componentService.deleteById(id)).willReturn(expectedResponse);
String actualResponse = mockMvc.perform(delete("/component/")
.param("componentId", String.valueOf(id))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
Assertions.assertEquals(expectedResponse, actualResponse);
}
@Test
void getCarComponentTest() throws Exception {
Long id = 1L;
String name = "Engine";
BigDecimal one = BigDecimal.ONE;
String manufacturer = "Ferrari";
var carComponentResponseDto = getComponentResponseDto(id, name, one, manufacturer);
given(componentService.getCarComponentById(id)).willReturn(carComponentResponseDto);
mockMvc.perform(get("/component/id")
.param("componentId", String.valueOf(id))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(id))
.andExpect(jsonPath("$.name").value(name))
.andExpect(jsonPath("$.price").value(one))
.andExpect(jsonPath("$.weight").value(one))
.andExpect(jsonPath("$.manufacturer").value(manufacturer));
}
@Test
void getAllCarComponentsTest() throws Exception {
List<CarComponentResponseDto> components = new ArrayList<>();
given(componentService.getAllCarComponents()).willReturn(components);
mockMvc.perform(get("/component/")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
}
package cz.muni.pa165.component.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
@WebMvcTest(ComponentController.class)
class ComponentInitControllerUnitTest {
@Autowired
private MockMvc mockMvc;
//@MockBean
//private ComponentInitFacade mockComponentInitFacade;
@Autowired
private ObjectMapper objectMapper;
}
package cz.muni.pa165.component.util;
import cz.muni.pa165.common_library.dtos.CarComponentRequestDto;
import cz.muni.pa165.common_library.dtos.CarComponentResponseDto;
import cz.muni.pa165.component.data.model.CarComponent;
import java.math.BigDecimal;
/**
* Helper class for creating Component objects.
*/
public class ComponentTestUtil {
/**
* Returns a CarComponent instance initialized with the given parameters.
*
* @param id the ID of the car component
* @param name the name of the car component
* @param decimal the weight and price of the car component
* @param manufacturer the manufacturer of the car component
* @return a CarComponent instance initialized with the given parameters
*/
public static CarComponent getComponent(Long id,
String name,
BigDecimal decimal,
String manufacturer) {
return CarComponent.builder()
.id(id)
.name(name)
.weight(decimal)
.price(decimal)
.manufacturer(manufacturer)
.build();
}
/**
* Returns a CarComponentResponseDto instance initialized with the given parameters.
*
* @param id the ID of the car component
* @param name the name of the car component
* @param decimal the weight and price of the car component
* @param manufacturer the manufacturer of the car component
* @return a CarComponentResponseDto instance initialized with the given parameters
*/
public static CarComponentResponseDto getComponentResponseDto(Long id,
String name,
BigDecimal decimal,
String manufacturer) {
return CarComponentResponseDto.builder()
.id(id)
.name(name)
.weight(decimal)
.price(decimal)
.manufacturer(manufacturer)
.build();
}
/**
* Returns a CarComponentResponseDto instance initialized with the given parameters.
*
* @param name the name of the car component
* @param decimal the weight and price of the car component
* @param manufacturer the manufacturer of the car component
* @return a CarComponentResponseDto instance initialized with the given parameters
*/
public static CarComponentRequestDto getComponentRequestDto(String name,
BigDecimal decimal,
String manufacturer) {
return CarComponentRequestDto.builder()
.name(name)
.weight(decimal)
.price(decimal)
.manufacturer(manufacturer)
.build();
}
}
package cz.muni.pa165.driver.data.repository; package cz.muni.pa165.driver.data.repository;
import cz.muni.pa165.driver.data.model.Driver; import cz.muni.pa165.driver.data.model.Driver;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
/** /**
...@@ -10,4 +14,10 @@ import org.springframework.stereotype.Repository; ...@@ -10,4 +14,10 @@ import org.springframework.stereotype.Repository;
@Repository @Repository
public interface DriverRepository extends JpaRepository<Driver, Long> { public interface DriverRepository extends JpaRepository<Driver, Long> {
@Query("SELECT d FROM Driver d WHERE d.id = :id")
Optional<Driver> findById(@Param("id") Long id);
@Query("SELECT d FROM Driver d")
List<Driver> findAll();
} }
...@@ -12,6 +12,7 @@ import java.util.List; ...@@ -12,6 +12,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
* Implementation of driver service. * Implementation of driver service.
...@@ -34,6 +35,7 @@ public class DriverServiceImpl implements DriverService { ...@@ -34,6 +35,7 @@ public class DriverServiceImpl implements DriverService {
* @param driverAddDto driver dto object * @param driverAddDto driver dto object
* @return dto of added driver * @return dto of added driver
*/ */
@Transactional
public DriverResponseDto addDriver(DriverAddDto driverAddDto) { public DriverResponseDto addDriver(DriverAddDto driverAddDto) {
var driver = driverMapper.convertToDriver(driverAddDto); var driver = driverMapper.convertToDriver(driverAddDto);
return driverMapper.convertToResponseDto(driverRepository.save(driver)); return driverMapper.convertToResponseDto(driverRepository.save(driver));
...@@ -46,6 +48,7 @@ public class DriverServiceImpl implements DriverService { ...@@ -46,6 +48,7 @@ public class DriverServiceImpl implements DriverService {
* @param driverUpdateDto data to be updated * @param driverUpdateDto data to be updated
* @return dto of updated driver * @return dto of updated driver
*/ */
@Transactional
public DriverResponseDto updateDriverById(Long id, DriverUpdateDto driverUpdateDto) { public DriverResponseDto updateDriverById(Long id, DriverUpdateDto driverUpdateDto) {
var driver = driverRepository.findById(id) var driver = driverRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Driver with given id not found.")); .orElseThrow(() -> new ResourceNotFoundException("Driver with given id not found."));
...@@ -59,6 +62,7 @@ public class DriverServiceImpl implements DriverService { ...@@ -59,6 +62,7 @@ public class DriverServiceImpl implements DriverService {
* @param driver existing driver * @param driver existing driver
* @param driverUpdateDto driver update dto * @param driverUpdateDto driver update dto
*/ */
@Transactional
private static void updateDriverAttributes(Driver driver, DriverUpdateDto driverUpdateDto) { private static void updateDriverAttributes(Driver driver, DriverUpdateDto driverUpdateDto) {
if (driverUpdateDto.name() != null) { if (driverUpdateDto.name() != null) {
driver.setName(driverUpdateDto.name()); driver.setName(driverUpdateDto.name());
...@@ -80,6 +84,7 @@ public class DriverServiceImpl implements DriverService { ...@@ -80,6 +84,7 @@ public class DriverServiceImpl implements DriverService {
* @param id driver id * @param id driver id
* @return dto of removed driver * @return dto of removed driver
*/ */
@Transactional
public DriverResponseDto removeDriverById(Long id) { public DriverResponseDto removeDriverById(Long id) {
var found = driverRepository.findById(id) var found = driverRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException( .orElseThrow(() -> new ResourceNotFoundException(
...@@ -93,6 +98,7 @@ public class DriverServiceImpl implements DriverService { ...@@ -93,6 +98,7 @@ public class DriverServiceImpl implements DriverService {
* *
* @return all stored drivers dto list * @return all stored drivers dto list
*/ */
@Transactional(readOnly = true)
public List<DriverInsightDto> getAllDrivers() { public List<DriverInsightDto> getAllDrivers() {
System.out.println(); System.out.println();
return driverRepository.findAll() return driverRepository.findAll()
...@@ -107,6 +113,7 @@ public class DriverServiceImpl implements DriverService { ...@@ -107,6 +113,7 @@ public class DriverServiceImpl implements DriverService {
* @param id driver id * @param id driver id
* @return found driver dto if successful * @return found driver dto if successful
*/ */
@Transactional(readOnly = true)
public DriverInsightDto getDriverById(Long id) { public DriverInsightDto getDriverById(Long id) {
return driverMapper.convertToInsightDto(driverRepository.findById(id) return driverMapper.convertToInsightDto(driverRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException( .orElseThrow(() -> new ResourceNotFoundException(
......
...@@ -26,4 +26,5 @@ public interface RaceRepository extends JpaRepository<Race, Long> { ...@@ -26,4 +26,5 @@ public interface RaceRepository extends JpaRepository<Race, Long> {
+ " JOIN r.raceInfo ri " + " JOIN r.raceInfo ri "
+ "WHERE ri.location = :location") + "WHERE ri.location = :location")
List<Race> findRacesByLocation(@Param("location") Location raceLocation); List<Race> findRacesByLocation(@Param("location") Location raceLocation);
} }
package cz.muni.pa165.race.data.repository; package cz.muni.pa165.race.data.repository;
import cz.muni.pa165.race.data.model.Season; import cz.muni.pa165.race.data.model.Season;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
/** /**
...@@ -9,4 +13,11 @@ import org.springframework.stereotype.Repository; ...@@ -9,4 +13,11 @@ import org.springframework.stereotype.Repository;
*/ */
@Repository @Repository
public interface SeasonRepository extends JpaRepository<Season, Long> { public interface SeasonRepository extends JpaRepository<Season, Long> {
@Query("SELECT s FROM Season s WHERE s.id = :id")
Optional<Season> findById(@Param("id") Long id);
@Query("SELECT s FROM Season s")
List<Season> findAll();
} }
...@@ -88,7 +88,7 @@ public class RaceController { ...@@ -88,7 +88,7 @@ public class RaceController {
return ResponseEntity.ok(raceService.assignPositionForDriverTwo(raceId, position)); return ResponseEntity.ok(raceService.assignPositionForDriverTwo(raceId, position));
} }
@Operation(summary = "Assign position for driver two") @Operation(summary = "Assign position for driver one")
@PatchMapping(path = "/assignPointsDriverOne", @PatchMapping(path = "/assignPointsDriverOne",
produces = MediaType.APPLICATION_JSON_VALUE) produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<RaceDto> assignPositionDriverOne(@RequestParam Long raceId, public ResponseEntity<RaceDto> assignPositionDriverOne(@RequestParam Long raceId,
......
package cz.muni.pa165.race.service;
import cz.muni.pa165.common_library.dtos.CarResponseDto;
import cz.muni.pa165.common_library.dtos.DriverDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
/**
* Getter for driver and car from appropriate modules.
*/
@Component
public class DbGetter {
@Autowired
RestTemplate client;
/**
* Calls driver module for a driver given by id.
*
* @param driverId id of a driver.
* @return driverDto.
*/
public DriverDto getDriver(Long driverId) {
var response =
client.getForEntity("http://localhost:8083/driver/get/id=" + driverId, DriverDto.class);
return response.getBody();
}
/**
* Calls car module for a car given by id.
*
* @param carId id of a car.
* @return carDto.
*/
public CarResponseDto getCar(Long carId) {
var response =
client.getForEntity("http://localhost:8082/car/?carId=" + carId, CarResponseDto.class);
return response.getBody();
}
}
package cz.muni.pa165.race.service; package cz.muni.pa165.race.service;
import cz.muni.pa165.common_library.dtos.CarResponseDto;
import cz.muni.pa165.common_library.dtos.DriverDto;
import cz.muni.pa165.common_library.dtos.Location; import cz.muni.pa165.common_library.dtos.Location;
import cz.muni.pa165.common_library.dtos.RaceDriverCarDto; import cz.muni.pa165.common_library.dtos.RaceDriverCarDto;
import cz.muni.pa165.common_library.dtos.RaceDto; import cz.muni.pa165.common_library.dtos.RaceDto;
...@@ -18,7 +16,7 @@ import java.util.Objects; ...@@ -18,7 +16,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate; import org.springframework.transaction.annotation.Transactional;
/** /**
* Service for managing races. * Service for managing races.
...@@ -32,7 +30,7 @@ public class RaceService implements RaceServiceI { ...@@ -32,7 +30,7 @@ public class RaceService implements RaceServiceI {
RaceRepository raceRepository; RaceRepository raceRepository;
@Autowired @Autowired
RestTemplate client; DbGetter dbGetter;
RaceService(RaceRepository raceRepository) { RaceService(RaceRepository raceRepository) {
this.raceRepository = raceRepository; this.raceRepository = raceRepository;
...@@ -44,8 +42,48 @@ public class RaceService implements RaceServiceI { ...@@ -44,8 +42,48 @@ public class RaceService implements RaceServiceI {
* @param raceDto race to insert. * @param raceDto race to insert.
* @return inserted race. * @return inserted race.
*/ */
@Transactional
public RaceDto postRace(RaceDto raceDto) { public RaceDto postRace(RaceDto raceDto) {
raceDto.setId(null); raceDto.setId(null);
if ((raceDto.getDriverOne() != null)
&& (raceDto.getDriverTwo() != null)) {
if (raceDto.getDriverOne().getDriverId() != null
&& raceDto.getDriverTwo().getDriverId() != null) {
if (Objects.equals(raceDto.getDriverOne().getCarId(),
raceDto.getDriverTwo().getCarId())) {
throw new DatabaseException("Cant assign same car to both drivers");
}
if (Objects.equals(raceDto.getDriverOne().getDriverId(),
raceDto.getDriverTwo().getDriverId())) {
throw new DatabaseException("Cant assign same driver to both drivers");
}
}
}
if (raceDto.getDriverOne() != null) {
if (raceDto.getDriverOne().getDriverId() != null) {
dbGetter.getDriver(raceDto.getDriverOne().getDriverId());
}
if (raceDto.getDriverOne().getCarId() != null) {
dbGetter.getCar(raceDto.getDriverOne().getCarId());
}
}
if (raceDto.getDriverTwo() != null) {
if (raceDto.getDriverTwo().getDriverId() != null) {
dbGetter.getDriver(raceDto.getDriverTwo().getDriverId());
}
if (raceDto.getDriverTwo().getCarId() != null) {
dbGetter.getCar(raceDto.getDriverTwo().getCarId());
}
}
if (raceDto.getDriverTwo() != null && raceDto.getDriverTwo().getDriverId() != null) {
dbGetter.getDriver(raceDto.getDriverTwo().getDriverId());
}
return convertRace(raceRepository.save(convertRaceDto(raceDto))); return convertRace(raceRepository.save(convertRaceDto(raceDto)));
} }
...@@ -54,6 +92,7 @@ public class RaceService implements RaceServiceI { ...@@ -54,6 +92,7 @@ public class RaceService implements RaceServiceI {
* *
* @param raceId race id * @param raceId race id
*/ */
@Transactional
public String deleteRace(Long raceId) { public String deleteRace(Long raceId) {
raceRepository.deleteById(raceId); raceRepository.deleteById(raceId);
return "Race with id: " + raceId + "was succesfully deleted"; return "Race with id: " + raceId + "was succesfully deleted";
...@@ -62,16 +101,17 @@ public class RaceService implements RaceServiceI { ...@@ -62,16 +101,17 @@ public class RaceService implements RaceServiceI {
/** /**
* Assigns driver one. * Assigns driver one.
*/ */
@Transactional
public RaceDto assignDriverOne(Long driverId, Long raceId, Long carId) { public RaceDto assignDriverOne(Long driverId, Long raceId, Long carId) {
var race = raceRepository.findById(raceId) var race = raceRepository.findById(raceId)
.orElseThrow(() -> new DatabaseException("Race not found")); .orElseThrow(() -> new DatabaseException("Race not found"));
var driver = getDriver(driverId); var driver = dbGetter.getDriver(driverId);
if (race.getDriver2() != null && Objects.equals(race.getDriver2().getDriverId(), driverId)) { if (race.getDriver2() != null && Objects.equals(race.getDriver2().getDriverId(), driverId)) {
throw new BadRequestException("Driver already assigned to the race as driver two"); throw new BadRequestException("Driver already assigned to the race as driver two");
} }
var car = getCar(carId); var car = dbGetter.getCar(carId);
if (race.getDriver2() != null && Objects.equals(race.getDriver2().getCarId(), carId)) { if (race.getDriver2() != null && Objects.equals(race.getDriver2().getCarId(), carId)) {
throw new BadRequestException("Car is already assigned to the race for driver two"); throw new BadRequestException("Car is already assigned to the race for driver two");
} }
...@@ -83,15 +123,16 @@ public class RaceService implements RaceServiceI { ...@@ -83,15 +123,16 @@ public class RaceService implements RaceServiceI {
/** /**
* Assigns driver two. * Assigns driver two.
*/ */
@Transactional
public RaceDto assignDriverTwo(Long driverId, Long raceId, Long carId) { public RaceDto assignDriverTwo(Long driverId, Long raceId, Long carId) {
var race = raceRepository.findById(raceId) var race = raceRepository.findById(raceId)
.orElseThrow(() -> new DatabaseException("Race not found")); .orElseThrow(() -> new DatabaseException("Race not found"));
var driver = getDriver(driverId); var driver = dbGetter.getDriver(driverId);
if (race.getDriver1() != null && Objects.equals(race.getDriver1().getDriverId(), driverId)) { if (race.getDriver1() != null && Objects.equals(race.getDriver1().getDriverId(), driverId)) {
throw new BadRequestException("Driver already assigned to the race as driver one"); throw new BadRequestException("Driver already assigned to the race as driver one");
} }
var car = getCar(carId); var car = dbGetter.getCar(carId);
if (race.getDriver1() != null && Objects.equals(race.getDriver1().getCarId(), carId)) { if (race.getDriver1() != null && Objects.equals(race.getDriver1().getCarId(), carId)) {
throw new BadRequestException("Car is already assigned to the race for driver two"); throw new BadRequestException("Car is already assigned to the race for driver two");
} }
...@@ -108,6 +149,7 @@ public class RaceService implements RaceServiceI { ...@@ -108,6 +149,7 @@ public class RaceService implements RaceServiceI {
* @param raceId id of race. * @param raceId id of race.
* @return found race. * @return found race.
*/ */
@Transactional(readOnly = true)
public RaceDto findRaceById(Long raceId) { public RaceDto findRaceById(Long raceId) {
return convertRace(raceRepository.findById(raceId).orElseThrow( return convertRace(raceRepository.findById(raceId).orElseThrow(
() -> new DatabaseException("Something went wrong when" () -> new DatabaseException("Something went wrong when"
...@@ -119,6 +161,7 @@ public class RaceService implements RaceServiceI { ...@@ -119,6 +161,7 @@ public class RaceService implements RaceServiceI {
* *
* @return found races. * @return found races.
*/ */
@Transactional(readOnly = true)
public List<RaceDto> findRaces() { public List<RaceDto> findRaces() {
return raceRepository.findAll().stream().map(this::convertRace).toList(); return raceRepository.findAll().stream().map(this::convertRace).toList();
} }
...@@ -126,10 +169,11 @@ public class RaceService implements RaceServiceI { ...@@ -126,10 +169,11 @@ public class RaceService implements RaceServiceI {
/** /**
* Assigns positions for driver number two. * Assigns positions for driver number two.
* *
* @param raceId race id. * @param raceId race id.
* @param position position of driver two. * @param position position of driver two.
* @return updated race. * @return updated race.
*/ */
@Transactional
public RaceDto assignPositionForDriverTwo(Long raceId, Integer position) { public RaceDto assignPositionForDriverTwo(Long raceId, Integer position) {
var race = var race =
raceRepository.findById(raceId).orElseThrow(() -> new DatabaseException("Race not found")); raceRepository.findById(raceId).orElseThrow(() -> new DatabaseException("Race not found"));
...@@ -140,14 +184,15 @@ public class RaceService implements RaceServiceI { ...@@ -140,14 +184,15 @@ public class RaceService implements RaceServiceI {
/** /**
* Assigns positions for driver number one. * Assigns positions for driver number one.
* *
* @param raceId race id. * @param raceId race id.
* @param position position of driver one. * @param position position of driver one.
* @return updated race. * @return updated race.
*/ */
@Transactional
public RaceDto assignPositionForDriverOne(Long raceId, Integer position) { public RaceDto assignPositionForDriverOne(Long raceId, Integer position) {
var race = var race =
raceRepository.findById(raceId).orElseThrow(() -> new DatabaseException("Race not found")); raceRepository.findById(raceId).orElseThrow(() -> new DatabaseException("Race not found"));
race.getDriver2().setFinalPosition(position); race.getDriver1().setFinalPosition(position);
return convertRace(raceRepository.save(race)); return convertRace(raceRepository.save(race));
} }
...@@ -157,6 +202,7 @@ public class RaceService implements RaceServiceI { ...@@ -157,6 +202,7 @@ public class RaceService implements RaceServiceI {
* @param location location of the race. * @param location location of the race.
* @return set if ids of most suitable drivers for given location. * @return set if ids of most suitable drivers for given location.
*/ */
@Transactional(readOnly = true)
public Set<Long> findMostSuitableDriver(Location location) { public Set<Long> findMostSuitableDriver(Location location) {
var races = raceRepository.findRacesByLocation(location); var races = raceRepository.findRacesByLocation(location);
Map<Long, Integer> driverWithPoints = new HashMap<>(); Map<Long, Integer> driverWithPoints = new HashMap<>();
...@@ -253,15 +299,5 @@ public class RaceService implements RaceServiceI { ...@@ -253,15 +299,5 @@ public class RaceService implements RaceServiceI {
return raceDto; return raceDto;
} }
private DriverDto getDriver(Long driverId) {
var response =
client.getForEntity("http://localhost:8083/driver/get/id=" + driverId, DriverDto.class);
return response.getBody();
}
private CarResponseDto getCar(Long carId) {
var response =
client.getForEntity("http://localhost:8082/car/?carId=" + carId, CarResponseDto.class);
return response.getBody();
}
} }
...@@ -10,6 +10,7 @@ import cz.muni.pa165.race.data.repository.SeasonRepository; ...@@ -10,6 +10,7 @@ import cz.muni.pa165.race.data.repository.SeasonRepository;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
* Season service. * Season service.
...@@ -33,6 +34,7 @@ public class SeasonService implements SeasonServiceI { ...@@ -33,6 +34,7 @@ public class SeasonService implements SeasonServiceI {
* @param seasonDto season to insert. * @param seasonDto season to insert.
* @return inserted season. * @return inserted season.
*/ */
@Transactional
public SeasonDto postSeason(SeasonDto seasonDto) { public SeasonDto postSeason(SeasonDto seasonDto) {
seasonDto.setId(null); seasonDto.setId(null);
return seasonConverter(seasonRepository.save(seasonDtoConverter(seasonDto))); return seasonConverter(seasonRepository.save(seasonDtoConverter(seasonDto)));
...@@ -44,6 +46,7 @@ public class SeasonService implements SeasonServiceI { ...@@ -44,6 +46,7 @@ public class SeasonService implements SeasonServiceI {
* @param seasonId season id. * @param seasonId season id.
* @return found season. * @return found season.
*/ */
@Transactional(readOnly = true)
public SeasonDto getSeasonById(Long seasonId) { public SeasonDto getSeasonById(Long seasonId) {
return seasonConverter(seasonRepository.findById(seasonId).orElseThrow( return seasonConverter(seasonRepository.findById(seasonId).orElseThrow(
() -> new DatabaseException("Something went wrong when" () -> new DatabaseException("Something went wrong when"
...@@ -55,6 +58,7 @@ public class SeasonService implements SeasonServiceI { ...@@ -55,6 +58,7 @@ public class SeasonService implements SeasonServiceI {
* *
* @return found seasons. * @return found seasons.
*/ */
@Transactional(readOnly = true)
public List<SeasonDto> getAllSeasons() { public List<SeasonDto> getAllSeasons() {
return seasonRepository.findAll() return seasonRepository.findAll()
.stream() .stream()
...@@ -68,6 +72,7 @@ public class SeasonService implements SeasonServiceI { ...@@ -68,6 +72,7 @@ public class SeasonService implements SeasonServiceI {
* @param seasonId season id. * @param seasonId season id.
* @return found season. * @return found season.
*/ */
@Transactional
public String deleteById(Long seasonId) { public String deleteById(Long seasonId) {
seasonRepository.deleteById(seasonId); seasonRepository.deleteById(seasonId);
return "Season with id: " + seasonId + "was succesfully deleted"; return "Season with id: " + seasonId + "was succesfully deleted";
...@@ -80,6 +85,7 @@ public class SeasonService implements SeasonServiceI { ...@@ -80,6 +85,7 @@ public class SeasonService implements SeasonServiceI {
* @param seasonId season id. * @param seasonId season id.
* @return modified race. * @return modified race.
*/ */
@Transactional(readOnly = true)
public SeasonDto addRace(Long raceId, Long seasonId) { public SeasonDto addRace(Long raceId, Long seasonId) {
var season = seasonRepository.findById(seasonId) var season = seasonRepository.findById(seasonId)
.orElseThrow(() -> new DatabaseException("Season not found")); .orElseThrow(() -> new DatabaseException("Season not found"));
......
package cz.muni.pa165.race.rest; package cz.muni.pa165.race.rest;
import cz.muni.pa165.race.data.model.Race;
import cz.muni.pa165.race.data.repository.RaceRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import java.util.List;
import java.util.Optional;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
...@@ -22,9 +8,24 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder ...@@ -22,9 +8,24 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import cz.muni.pa165.common_library.dtos.CarResponseDto;
import cz.muni.pa165.common_library.dtos.DriverDto;
import cz.muni.pa165.race.data.model.Race;
import cz.muni.pa165.race.data.repository.RaceRepository;
import cz.muni.pa165.race.service.DbGetter;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest @SpringBootTest
@AutoConfigureMockMvc @AutoConfigureMockMvc
...@@ -40,8 +41,22 @@ class RaceControllerTest { ...@@ -40,8 +41,22 @@ class RaceControllerTest {
} }
} }
"""; """;
private String expectedMessagePost = "{\"id\":1,\"raceInfo\":{\"location\":\"MONACO\",\"name\":\"Monaco Grand Prix 2023\",\"prizePool\":30000000},\"driverOne\":{\"driverId\":1,\"carId\":1,\"position\":null},\"driverTwo\":{\"driverId\":2,\"carId\":2,\"position\":null}}"; private String expectedMessagePost = "{\"id\":1,\"raceInfo\":{\"location\":\"MONACO\","
+ "\"name\":\"Monaco Grand Prix 2023\",\"prizePool\":30000000},\"driverOne\""
+ ":{\"driverId\":1,\"carId\":1,\"position\":null},\"driverTwo\":{\"driverId\""
+ ":2,\"carId\":2,\"position\":null}}";
private String expectedMessageAssignTwo = "{\"id\":1,\"raceInfo\":{\"location\":"
+ "\"MONACO\",\"name\":\"Monaco Grand Prix 2023\",\"prizePool\":30000000},"
+ "\"driverOne\":{\"driverId\":1,\"carId\":1,\"position\":null},\"driverTwo\""
+ ":{\"driverId\":1,\"carId\":1,\"position\":null}}";
private String expectedMessageGet = "{\"id\":1,\"raceInfo\":{\"location\":\"MONACO\""
+ ",\"name\":\"Monaco Grand Prix 2023\",\"prizePool\":30000000},\"driverOne\""
+ ":{\"driverId\":1,\"carId\":1,\"position\":null},\"driverTwo\":{\"driverId\""
+ ":2,\"carId\":2,\"position\":null}}";
private String expectedMessageGetAll = "[{\"id\":1,\"raceInfo\":{\"location\""
+ ":\"MONACO\",\"name\":\"Monaco Grand Prix 2023\",\"prizePool\":30000000},\""
+ "driverOne\":{\"driverId\":1,\"carId\":1,\"position\":null},\"driverTwo\":{\""
+ "driverId\":2,\"carId\":2,\"position\":null}}]";
@Autowired @Autowired
private MockMvc mockMvc; private MockMvc mockMvc;
...@@ -49,6 +64,9 @@ class RaceControllerTest { ...@@ -49,6 +64,9 @@ class RaceControllerTest {
@MockBean @MockBean
private RaceRepository raceRepository; private RaceRepository raceRepository;
@MockBean
private DbGetter dbGetter;
@BeforeEach @BeforeEach
void setup() { void setup() {
Race raceDao = RaceTestUtil.getDaoRace(); Race raceDao = RaceTestUtil.getDaoRace();
...@@ -57,6 +75,10 @@ class RaceControllerTest { ...@@ -57,6 +75,10 @@ class RaceControllerTest {
given(raceRepository.findById(anyLong())).willReturn( given(raceRepository.findById(anyLong())).willReturn(
Optional.of(raceDao)); Optional.of(raceDao));
given(raceRepository.findAll()).willReturn(List.of(raceDao)); given(raceRepository.findAll()).willReturn(List.of(raceDao));
CarResponseDto carDao = RaceTestUtil.getCarDao();
given(dbGetter.getCar(anyLong())).willReturn(carDao);
DriverDto driverDto = RaceTestUtil.getDriverDao();
given(dbGetter.getDriver(anyLong())).willReturn(driverDto);
} }
...@@ -65,7 +87,6 @@ class RaceControllerTest { ...@@ -65,7 +87,6 @@ class RaceControllerTest {
var request = post("/race/") var request = post("/race/")
.content(bodyContent) .content(bodyContent)
.contentType(MediaType.APPLICATION_JSON_VALUE); .contentType(MediaType.APPLICATION_JSON_VALUE);
this.mockMvc.perform(request) this.mockMvc.perform(request)
.andDo(print()) .andDo(print())
.andExpect(status().isOk()) .andExpect(status().isOk())
...@@ -75,7 +96,6 @@ class RaceControllerTest { ...@@ -75,7 +96,6 @@ class RaceControllerTest {
@Test @Test
void deleteRace() throws Exception { void deleteRace() throws Exception {
String expectedMessage = "Race with id: 1was succesfully deleted"; String expectedMessage = "Race with id: 1was succesfully deleted";
var requestDelete = delete("/race/") var requestDelete = delete("/race/")
.param("raceId", "1") .param("raceId", "1")
.contentType(MediaType.APPLICATION_JSON_VALUE); .contentType(MediaType.APPLICATION_JSON_VALUE);
...@@ -87,26 +107,22 @@ class RaceControllerTest { ...@@ -87,26 +107,22 @@ class RaceControllerTest {
@Test @Test
void getExistingRace() throws Exception { void getExistingRace() throws Exception {
String expectedMessage = "{\"id\":1,\"raceInfo\":{\"location\":\"MONACO\",\"name\":\"Monaco Grand Prix 2023\",\"prizePool\":30000000},\"driverOne\":{\"driverId\":1,\"carId\":1,\"position\":null},\"driverTwo\":{\"driverId\":2,\"carId\":2,\"position\":null}}";
var requestGet = get("/race/id") var requestGet = get("/race/id")
.param("raceId", "1") .param("raceId", "1")
.contentType(MediaType.APPLICATION_JSON_VALUE); .contentType(MediaType.APPLICATION_JSON_VALUE);
this.mockMvc.perform(requestGet) this.mockMvc.perform(requestGet)
.andDo(print()) .andDo(print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(expectedMessage)); .andExpect(content().string(expectedMessageGet));
} }
@Test @Test
void getAllRaces() throws Exception { void getAllRaces() throws Exception {
var requestGet = get("/race/"); var requestGet = get("/race/");
String expectedMessage = "[{\"id\":1,\"raceInfo\":{\"location\":\"MONACO\",\"name\":\"Monaco Grand Prix 2023\",\"prizePool\":30000000},\"driverOne\":{\"driverId\":1,\"carId\":1,\"position\":null},\"driverTwo\":{\"driverId\":2,\"carId\":2,\"position\":null}}]";
this.mockMvc.perform(requestGet) this.mockMvc.perform(requestGet)
.andDo(print()) .andDo(print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(expectedMessage)); .andExpect(content().string(expectedMessageGetAll));
} }
@Test @Test
...@@ -114,13 +130,25 @@ class RaceControllerTest { ...@@ -114,13 +130,25 @@ class RaceControllerTest {
var requestAssign = patch("/race/assignDriverOne") var requestAssign = patch("/race/assignDriverOne")
.param("driverOneId", "1") .param("driverOneId", "1")
.param("raceId", "1") .param("raceId", "1")
.param("carId", "2") .param("carId", "1")
.contentType(MediaType.APPLICATION_JSON_VALUE); .contentType(MediaType.APPLICATION_JSON_VALUE);
this.mockMvc.perform(requestAssign) this.mockMvc.perform(requestAssign)
.andDo(print()) .andDo(print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(expectedMessagePost)); .andExpect(content().string(expectedMessagePost));
} }
@Test
void assignDriverTwo() throws Exception {
var requestAssign = patch("/race/assignDriverTwo")
.param("driverTwoId", "2")
.param("raceId", "2")
.param("carId", "2")
.contentType(MediaType.APPLICATION_JSON_VALUE);
this.mockMvc.perform(requestAssign)
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(expectedMessageAssignTwo));
}
} }