diff --git a/service-course-api/build.gradle b/service-course-api/build.gradle
index 94a1913..0270147 100644
--- a/service-course-api/build.gradle
+++ b/service-course-api/build.gradle
@@ -27,7 +27,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.netflix.graphql.dgs:graphql-dgs-extended-scalars'
testImplementation "org.mockito:mockito-core:3.+"
- implementation 'com.graphql-java:graphql-java:21.2'
+ implementation 'com.graphql-java:graphql-java:21.2' // Locked version to avoid problems
+ implementation 'org.springframework.boot:spring-boot-starter-cache'
+ implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8'
}
generateJava {
diff --git a/service-course-api/src/main/java/servicecourse/CacheConfiguration.java b/service-course-api/src/main/java/servicecourse/CacheConfiguration.java
new file mode 100644
index 0000000..f45fa60
--- /dev/null
+++ b/service-course-api/src/main/java/servicecourse/CacheConfiguration.java
@@ -0,0 +1,16 @@
+package servicecourse;
+
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.caffeine.CaffeineCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class CacheConfiguration {
+ public static final String BIKE_BRANDS = "bikeBrands";
+
+ @Bean
+ public CacheManager cacheManager() {
+ return new CaffeineCacheManager(BIKE_BRANDS);
+ }
+}
diff --git a/service-course-api/src/main/java/servicecourse/ServiceCourseApplication.java b/service-course-api/src/main/java/servicecourse/ServiceCourseApplication.java
index 2abb576..ebfb17a 100644
--- a/service-course-api/src/main/java/servicecourse/ServiceCourseApplication.java
+++ b/service-course-api/src/main/java/servicecourse/ServiceCourseApplication.java
@@ -2,8 +2,10 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
+@EnableCaching
public class ServiceCourseApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceCourseApplication.class, args);
diff --git a/service-course-api/src/main/java/servicecourse/datafetchers/BikeBrandsDataFetcher.java b/service-course-api/src/main/java/servicecourse/datafetchers/BikeBrandsDataFetcher.java
index a9fc4cb..7556b50 100644
--- a/service-course-api/src/main/java/servicecourse/datafetchers/BikeBrandsDataFetcher.java
+++ b/service-course-api/src/main/java/servicecourse/datafetchers/BikeBrandsDataFetcher.java
@@ -2,33 +2,32 @@
import com.netflix.graphql.dgs.*;
import lombok.RequiredArgsConstructor;
+import org.dataloader.DataLoader;
import servicecourse.generated.types.BikeBrand;
import servicecourse.generated.types.CreateBikeBrandInput;
import servicecourse.generated.types.Model;
import servicecourse.services.bikebrands.BikeBrandsService;
-import servicecourse.services.models.ModelsService;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
@DgsComponent
@RequiredArgsConstructor
public class BikeBrandsDataFetcher {
- private final ModelsService modelsService;
private final BikeBrandsService bikeBrandsService;
/**
- * This is an enhanced attribute. Services will not generate it ahead of time, unlike brand
- * name. Therefore, if specified, it must be computed here.
+ * This is an enhanced attribute. Services will not generate it ahead of time (unlike brand
+ * name). Therefore, if specified by the user, it must be computed here.
+ *
+ * A data loader is used to avoid sending multiple separate requests to the models service when
+ * handling a request that involves multiple bike brands (see {@link #bikeBrands()}).
*/
@DgsData(parentType = "BikeBrand", field = "models")
- public List models(DgsDataFetchingEnvironment dfe) {
+ public CompletableFuture> models(DgsDataFetchingEnvironment dfe) {
BikeBrand bikeBrand = dfe.getSource();
- // Data loader here
- // Why?
- // Because if some wind up merchant decides to ask for models on all bike brands
- // after running bikeBrands query
- // Models service will get pinged N+1 times
- return modelsService.findByBrandName(bikeBrand.getName());
+ DataLoader> modelsDataLoader = dfe.getDataLoader("models");
+ return modelsDataLoader.load(bikeBrand.getName());
}
@DgsQuery
diff --git a/service-course-api/src/main/java/servicecourse/repo/ModelRepository.java b/service-course-api/src/main/java/servicecourse/repo/ModelRepository.java
index 955f6e8..104b560 100644
--- a/service-course-api/src/main/java/servicecourse/repo/ModelRepository.java
+++ b/service-course-api/src/main/java/servicecourse/repo/ModelRepository.java
@@ -8,5 +8,7 @@
@Repository
public interface ModelRepository extends JpaRepository, JpaSpecificationExecutor {
- List findAllByBrandName(String brandName);
+ List findByBrandName(String brandName);
+
+ List findByBrandNameIn(List brandNames);
}
diff --git a/service-course-api/src/main/java/servicecourse/repo/URLConverter.java b/service-course-api/src/main/java/servicecourse/repo/URLConverter.java
index 82fe8ae..4d57f8d 100644
--- a/service-course-api/src/main/java/servicecourse/repo/URLConverter.java
+++ b/service-course-api/src/main/java/servicecourse/repo/URLConverter.java
@@ -5,6 +5,7 @@
import java.net.MalformedURLException;
import java.net.URL;
+/** Converts a potentially null URL */
public class URLConverter implements AttributeConverter {
@Override
public String convertToDatabaseColumn(URL url) {
diff --git a/service-course-api/src/main/java/servicecourse/repo/specification/StringFilterSpecification.java b/service-course-api/src/main/java/servicecourse/repo/specification/StringFilterSpecification.java
new file mode 100644
index 0000000..8b2591a
--- /dev/null
+++ b/service-course-api/src/main/java/servicecourse/repo/specification/StringFilterSpecification.java
@@ -0,0 +1,16 @@
+package servicecourse.repo.specification;
+
+import servicecourse.generated.types.StringFilterInput;
+
+import java.util.Optional;
+import java.util.function.Predicate;
+
+public class StringFilterSpecification {
+ private StringFilterSpecification() { }
+
+ public static Predicate from(StringFilterInput input) {
+ return arg -> Optional.ofNullable(input.getEquals()).map(arg::equals).orElse(true)
+ || Optional.ofNullable(input.getContains()).map(arg::contains).orElse(true)
+ || Optional.ofNullable(input.getIn()).map(in -> in.contains(arg)).orElse(true);
+ }
+}
diff --git a/service-course-api/src/main/java/servicecourse/services/bikebrands/RelationalBikeBrandsService.java b/service-course-api/src/main/java/servicecourse/services/bikebrands/BikeBrandsServiceImpl.java
similarity index 72%
rename from service-course-api/src/main/java/servicecourse/services/bikebrands/RelationalBikeBrandsService.java
rename to service-course-api/src/main/java/servicecourse/services/bikebrands/BikeBrandsServiceImpl.java
index 0a75557..0062812 100644
--- a/service-course-api/src/main/java/servicecourse/services/bikebrands/RelationalBikeBrandsService.java
+++ b/service-course-api/src/main/java/servicecourse/services/bikebrands/BikeBrandsServiceImpl.java
@@ -1,7 +1,10 @@
package servicecourse.services.bikebrands;
import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
+import servicecourse.CacheConfiguration;
import servicecourse.generated.types.BikeBrand;
import servicecourse.generated.types.CreateBikeBrandInput;
import servicecourse.repo.BikeBrandEntity;
@@ -13,10 +16,11 @@
@Service
@RequiredArgsConstructor
-public class RelationalBikeBrandsService implements BikeBrandsService {
+public class BikeBrandsServiceImpl implements BikeBrandsService {
private final BikeBrandRepository bikeBrandRepository;
@Override
+ @CacheEvict(value = CacheConfiguration.BIKE_BRANDS)
public BikeBrand createBikeBrand(CreateBikeBrandInput input) {
// Validate that the brand doesn't already exist
bikeBrandRepository.findById(input.getName())
@@ -26,6 +30,7 @@ public BikeBrand createBikeBrand(CreateBikeBrandInput input) {
}
@Override
+ @CacheEvict(value = CacheConfiguration.BIKE_BRANDS)
public String deleteBikeBrand(String name) {
return bikeBrandRepository.findById(name).map((entity) -> {
bikeBrandRepository.deleteById(name);
@@ -33,7 +38,12 @@ public String deleteBikeBrand(String name) {
}).orElseThrow(Errors::newBikeBrandNotFoundError);
}
+ /**
+ * This method is cached. The cache is invalidated by {@link #createBikeBrand} and
+ * {@link #deleteBikeBrand}.
+ */
@Override
+ @Cacheable(value = CacheConfiguration.BIKE_BRANDS, sync = true)
public List bikeBrands() {
return bikeBrandRepository.findAll()
.stream()
diff --git a/service-course-api/src/main/java/servicecourse/services/bikes/RelationalBikesService.java b/service-course-api/src/main/java/servicecourse/services/bikes/BikesServiceImpl.java
similarity index 98%
rename from service-course-api/src/main/java/servicecourse/services/bikes/RelationalBikesService.java
rename to service-course-api/src/main/java/servicecourse/services/bikes/BikesServiceImpl.java
index 50217f6..11a6d38 100644
--- a/service-course-api/src/main/java/servicecourse/services/bikes/RelationalBikesService.java
+++ b/service-course-api/src/main/java/servicecourse/services/bikes/BikesServiceImpl.java
@@ -16,7 +16,7 @@
@Service
@RequiredArgsConstructor
-public class RelationalBikesService implements BikesService {
+public class BikesServiceImpl implements BikesService {
private final BikeRepository bikeRepository;
private final ModelRepository modelRepository;
private final GroupsetRespository groupsetRespository;
diff --git a/service-course-api/src/main/java/servicecourse/services/groupsets/GroupsetServiceImpl.java b/service-course-api/src/main/java/servicecourse/services/groupsets/GroupsetServiceImpl.java
new file mode 100644
index 0000000..214f22b
--- /dev/null
+++ b/service-course-api/src/main/java/servicecourse/services/groupsets/GroupsetServiceImpl.java
@@ -0,0 +1,4 @@
+package servicecourse.services.groupsets;
+
+public class GroupsetServiceImpl implements GroupsetService {
+}
diff --git a/service-course-api/src/main/java/servicecourse/services/groupsets/RelationalGroupsetService.java b/service-course-api/src/main/java/servicecourse/services/groupsets/RelationalGroupsetService.java
deleted file mode 100644
index 16a2088..0000000
--- a/service-course-api/src/main/java/servicecourse/services/groupsets/RelationalGroupsetService.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package servicecourse.services.groupsets;
-
-public class RelationalGroupsetService implements GroupsetService {
-}
diff --git a/service-course-api/src/main/java/servicecourse/services/models/ModelsService.java b/service-course-api/src/main/java/servicecourse/services/models/ModelsService.java
index a56421d..e3bc449 100644
--- a/service-course-api/src/main/java/servicecourse/services/models/ModelsService.java
+++ b/service-course-api/src/main/java/servicecourse/services/models/ModelsService.java
@@ -7,11 +7,17 @@
import java.util.Map;
public interface ModelsService {
+ /**
+ * @return all models belonging to the brand
+ */
List findByBrandName(String brandName);
Model createModel(CreateModelInput input);
String deleteModel(String id);
+ /**
+ * @return a map; bike brand name -> models for that brand
+ */
Map> modelsForBikeBrands(List brandNames);
}
diff --git a/service-course-api/src/main/java/servicecourse/services/models/RelationalModelsService.java b/service-course-api/src/main/java/servicecourse/services/models/ModelsServiceImpl.java
similarity index 72%
rename from service-course-api/src/main/java/servicecourse/services/models/RelationalModelsService.java
rename to service-course-api/src/main/java/servicecourse/services/models/ModelsServiceImpl.java
index fbac659..2a8d261 100644
--- a/service-course-api/src/main/java/servicecourse/services/models/RelationalModelsService.java
+++ b/service-course-api/src/main/java/servicecourse/services/models/ModelsServiceImpl.java
@@ -2,7 +2,6 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
-import servicecourse.generated.types.BikeBrand;
import servicecourse.generated.types.CreateModelInput;
import servicecourse.generated.types.Model;
import servicecourse.repo.BikeBrandRepository;
@@ -10,20 +9,19 @@
import servicecourse.repo.ModelRepository;
import servicecourse.services.Errors;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
-public class RelationalModelsService implements ModelsService {
+public class ModelsServiceImpl implements ModelsService {
private final ModelRepository modelRepository;
private final BikeBrandRepository bikeBrandRepository;
@Override
public List findByBrandName(String brandName) {
- return modelRepository.findAllByBrandName(brandName)
+ return modelRepository.findByBrandName(brandName)
.stream()
.map(ModelEntity::asModel)
.collect(Collectors.toList());
@@ -55,14 +53,10 @@ public String deleteModel(String id) {
}
public Map> modelsForBikeBrands(List brandNames) {
- Map> result = new HashMap<>();
- result.put("hello", List.of(Model.newBuilder()
- .name("hello")
- .brand(BikeBrand.newBuilder()
- .name("hello").build())
- .modelYear(2022)
- .build()));
- return result;
+ return modelRepository.findByBrandNameIn(brandNames)
+ .stream()
+ .map(ModelEntity::asModel)
+ .collect(Collectors.groupingBy(m -> m.getBrand().getName()));
}
}
diff --git a/service-course-api/src/main/resources/schema/schema.graphqls b/service-course-api/src/main/resources/schema/schema.graphqls
index 786f888..636e98c 100644
--- a/service-course-api/src/main/resources/schema/schema.graphqls
+++ b/service-course-api/src/main/resources/schema/schema.graphqls
@@ -15,15 +15,40 @@ scalar Date
# Utils
+enum Op {
+ OR
+ AND
+}
+
input DateRangeFilterInput {
from: Date!
to: Date!
}
+"""
+Fields are combined with OR logic
+"""
+input StringFilterInput {
+ contains: String
+ in: [String!]
+ equals: String
+}
+
+input IntegerFilterInput {
+ lessThanOrEqualTo: Int
+ greaterThanOrEqualTo: Int
+ equals: Int
+ in: [Int!]
+ operator: Op
+}
+
# Queries and mutations
type Query {
- bikes(filter: BikesFilterInput): [Bike!]
+ bikes(filter: BikesFilterInput): [Bike!]!
+ """
+ All bike brands
+ """
bikeBrands: [BikeBrand!]!
# """
# Get the available days to book for a give bike for a given date range.
@@ -47,7 +72,7 @@ type Mutation {
deleteBikeBrand(name: String!): String
}
-# Models
+# Bike brands
type BikeBrand {
name: String!
@@ -58,6 +83,8 @@ input CreateBikeBrandInput {
name: String!
}
+# Models
+
type Model {
id: ID!
name: String!
@@ -71,6 +98,15 @@ input CreateModelInput {
brandName: String!
}
+"""
+Fields are combined with AND logic
+"""
+input ModelFilterInput {
+ name: StringFilterInput
+ modelYear: IntegerFilterInput
+ brandName: String
+}
+
# Bikes
type Bike {
@@ -85,11 +121,23 @@ input BikesFilterInput {
"""
If specified, return only bikes that are available in the provided date range
"""
- availableDateRangeFilter: DateRangeFilterInput
+ availableDateRange: DateRangeFilterInput
+ """
+ If specified, return only bikes whose model matches the criteria
+ """
+ model: ModelFilterInput
+ """
+ If specified, return only bikes with a groupset matching the criteria
+ """
+ groupset: GroupsetFilterInput
+ size: StringFilterInput
}
input CreateBikeInput {
modelId: ID!
+ """
+ There must be a groupset with this name already saved otherwise the mutation will fail
+ """
groupsetName: String!
size: String!
heroImageUrl: Url
@@ -97,6 +145,9 @@ input CreateBikeInput {
input UpdateBikeInput {
bikeId: ID!
+ """
+ IF specified, there must be a groupset with this name already saved otherwise the mutation will fail
+ """
groupsetName: String
heroImageUrl: Url
}
@@ -114,3 +165,12 @@ type Groupset {
brand: GroupsetBrand!
isElectronic: Boolean!
}
+
+"""
+Fields are combined with AND logic
+"""
+input GroupsetFilterInput {
+ name: String
+ brand: GroupsetBrand
+ isElectronic: Boolean
+}
diff --git a/service-course-api/src/test/java/servicecourse/services/bikebrands/RelationalBikeBrandsServiceTest.java b/service-course-api/src/test/java/servicecourse/services/bikebrands/BikeBrandsServiceImplTest.java
similarity index 82%
rename from service-course-api/src/test/java/servicecourse/services/bikebrands/RelationalBikeBrandsServiceTest.java
rename to service-course-api/src/test/java/servicecourse/services/bikebrands/BikeBrandsServiceImplTest.java
index 7ff46c3..9e9a438 100644
--- a/service-course-api/src/test/java/servicecourse/services/bikebrands/RelationalBikeBrandsServiceTest.java
+++ b/service-course-api/src/test/java/servicecourse/services/bikebrands/BikeBrandsServiceImplTest.java
@@ -20,14 +20,14 @@
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
-public class RelationalBikeBrandsServiceTest {
+public class BikeBrandsServiceImplTest {
@Mock
BikeBrandRepository mockBikeBrandRepository;
- RelationalBikeBrandsService relationalBikesBrandsService;
+ BikeBrandsServiceImpl bikeBrandsService;
@BeforeEach
void setup() {
- relationalBikesBrandsService = new RelationalBikeBrandsService(mockBikeBrandRepository);
+ bikeBrandsService = new BikeBrandsServiceImpl(mockBikeBrandRepository);
}
@Nested
@@ -42,9 +42,9 @@ void fail_because_bike_brand_already_exists() {
// When we call the createBikeBrand method with that name
// Then the method should throw
assertThrows(IllegalArgumentException.class,
- () -> relationalBikesBrandsService.createBikeBrand(CreateBikeBrandInput.newBuilder()
- .name(bikeBrandName)
- .build()));
+ () -> bikeBrandsService.createBikeBrand(CreateBikeBrandInput.newBuilder()
+ .name(bikeBrandName)
+ .build()));
}
@Test
@@ -61,9 +61,9 @@ void success() {
.thenReturn(expectedEntity);
// When we call the createBikeBrand method with that name
- BikeBrand result = relationalBikesBrandsService.createBikeBrand(CreateBikeBrandInput.newBuilder()
- .name(bikeBrandName)
- .build());
+ BikeBrand result = bikeBrandsService.createBikeBrand(CreateBikeBrandInput.newBuilder()
+ .name(bikeBrandName)
+ .build());
// Then we should have received the expected BikeBrand object
assertThat(result).isEqualTo(expectedEntity.asBikeBrand());
@@ -81,7 +81,7 @@ void fail_because_no_bike_brand() {
// When we call the deleteBikeBrand method with that name
// Then the method should throw
assertThrows(NoSuchElementException.class,
- () -> relationalBikesBrandsService.deleteBikeBrand(ghostBikeBrandName));
+ () -> bikeBrandsService.deleteBikeBrand(ghostBikeBrandName));
}
@Test
@@ -92,7 +92,7 @@ void success() {
.thenReturn(Optional.of(BikeBrandEntity.ofName(bikeBrandName)));
// When we call deleteBikeBrand with that name
- String result = relationalBikesBrandsService.deleteBikeBrand(bikeBrandName);
+ String result = bikeBrandsService.deleteBikeBrand(bikeBrandName);
// Then the repository should have been asked to delete the bike brand
verify(mockBikeBrandRepository).deleteById(bikeBrandName);
diff --git a/service-course-api/src/test/java/servicecourse/services/bikes/RelationalBikesServiceTest.java b/service-course-api/src/test/java/servicecourse/services/bikes/BikesServiceImplTest.java
similarity index 78%
rename from service-course-api/src/test/java/servicecourse/services/bikes/RelationalBikesServiceTest.java
rename to service-course-api/src/test/java/servicecourse/services/bikes/BikesServiceImplTest.java
index 9fbc1fe..f497c3c 100644
--- a/service-course-api/src/test/java/servicecourse/services/bikes/RelationalBikesServiceTest.java
+++ b/service-course-api/src/test/java/servicecourse/services/bikes/BikesServiceImplTest.java
@@ -24,20 +24,20 @@
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
-public class RelationalBikesServiceTest {
+public class BikesServiceImplTest {
@Mock
BikeRepository mockBikeRepository;
@Mock
ModelRepository mockModelRepository;
@Mock
GroupsetRespository mockGroupsetRepository;
- RelationalBikesService relationalBikesService;
+ BikesServiceImpl bikesService;
@BeforeEach
void beforeEach() {
- relationalBikesService = new RelationalBikesService(mockBikeRepository,
- mockModelRepository,
- mockGroupsetRepository);
+ bikesService = new BikesServiceImpl(mockBikeRepository,
+ mockModelRepository,
+ mockGroupsetRepository);
}
@Test
@@ -47,7 +47,7 @@ void bikes() {
// When
when(mockBikeRepository.findAll()).thenReturn(List.of(result));
- List bikes = relationalBikesService.bikes(null);
+ List bikes = bikesService.bikes(null);
// Then
assertThat(bikes).isEqualTo(List.of(result.asBike()));
@@ -64,12 +64,12 @@ void model_entity_not_found() {
// When trying to create a bike with that model
// Then createBike should throw
assertThrows(NoSuchElementException.class,
- () -> relationalBikesService.createBike(CreateBikeInput.newBuilder()
- .modelId(BikeId.serialize(
- ghostModelId))
- .groupsetName("name")
- .size("Medium")
- .build()));
+ () -> bikesService.createBike(CreateBikeInput.newBuilder()
+ .modelId(BikeId.serialize(
+ ghostModelId))
+ .groupsetName("name")
+ .size("Medium")
+ .build()));
}
@Test
@@ -86,13 +86,13 @@ void groupset_entity_not_found() {
// When trying to create a bike with that groupset
// Then createBike should throw
assertThrows(NoSuchElementException.class,
- () -> relationalBikesService.createBike(CreateBikeInput.newBuilder()
- .modelId(BikeId.serialize(
- modelId))
- .groupsetName(
- ghostGroupsetName)
- .size("Medium")
- .build()));
+ () -> bikesService.createBike(CreateBikeInput.newBuilder()
+ .modelId(BikeId.serialize(
+ modelId))
+ .groupsetName(
+ ghostGroupsetName)
+ .size("Medium")
+ .build()));
}
@Test
@@ -126,13 +126,13 @@ void successful_save() {
.thenReturn(expectedSavedBikeEntity);
// When we call the createBike method
- Bike result = relationalBikesService.createBike(CreateBikeInput.newBuilder()
- .size(mockSize)
- .groupsetName(mockGroupsetName)
- .modelId(BikeId.serialize(
- mockModelId))
- .heroImageUrl(mockUrl)
- .build());
+ Bike result = bikesService.createBike(CreateBikeInput.newBuilder()
+ .size(mockSize)
+ .groupsetName(mockGroupsetName)
+ .modelId(BikeId.serialize(
+ mockModelId))
+ .heroImageUrl(mockUrl)
+ .build());
// Then we should have received the expected Bike object
assertThat(result).isEqualTo(expectedSavedBikeEntity.asBike());
@@ -155,7 +155,7 @@ void bike_entity_not_found() {
// When we call the updateBike method with this input
// Then it should throw
assertThrows(NoSuchElementException.class,
- () -> relationalBikesService.updateBike(input));
+ () -> bikesService.updateBike(input));
}
@Test
@@ -179,7 +179,7 @@ void groupset_entity_not_found() {
// When we call the updateBike method with this input
// Then it should throw
assertThrows(NoSuchElementException.class,
- () -> relationalBikesService.updateBike(input));
+ () -> bikesService.updateBike(input));
}
@Test
@@ -215,7 +215,7 @@ void success() {
.build();
// When we call the updateBike method
- Bike result = relationalBikesService.updateBike(input);
+ Bike result = bikesService.updateBike(input);
// Then we should get back the bike we expected
assertThat(result).isEqualTo(expectedNewBikeEntity.asBike());
@@ -236,7 +236,7 @@ void fail_because_no_bike() {
// When we call the deleteBike method with that id
// Then the method should throw
assertThrows(NoSuchElementException.class,
- () -> relationalBikesService.deleteBike(BikeId.serialize(ghostBikeId)));
+ () -> bikesService.deleteBike(BikeId.serialize(ghostBikeId)));
}
@Test
@@ -247,7 +247,7 @@ void success() {
.thenReturn(Optional.of(EntityFactory.newBikeEntityWithId(bikeId)));
// When we call the deleteBike method with that id
- Long result = relationalBikesService.deleteBike(BikeId.serialize(bikeId));
+ Long result = bikesService.deleteBike(BikeId.serialize(bikeId));
// Then the repository should have been asked to delete the bike
verify(mockBikeRepository).deleteById(bikeId);
diff --git a/service-course-api/src/test/java/servicecourse/services/models/RelationalModelsServiceTest.java b/service-course-api/src/test/java/servicecourse/services/models/ModelsServiceImplTest.java
similarity index 87%
rename from service-course-api/src/test/java/servicecourse/services/models/RelationalModelsServiceTest.java
rename to service-course-api/src/test/java/servicecourse/services/models/ModelsServiceImplTest.java
index 19f1754..a26f6a7 100644
--- a/service-course-api/src/test/java/servicecourse/services/models/RelationalModelsServiceTest.java
+++ b/service-course-api/src/test/java/servicecourse/services/models/ModelsServiceImplTest.java
@@ -23,17 +23,17 @@
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
-public class RelationalModelsServiceTest {
+public class ModelsServiceImplTest {
@Mock
ModelRepository mockModelRepository;
@Mock
BikeBrandRepository mockBikeBrandRepository;
- RelationalModelsService relationalModelsService;
+ ModelsServiceImpl modelsService;
@BeforeEach
void setup() {
- relationalModelsService = new RelationalModelsService(mockModelRepository,
- mockBikeBrandRepository);
+ modelsService = new ModelsServiceImpl(mockModelRepository,
+ mockBikeBrandRepository);
}
@Nested
@@ -54,7 +54,7 @@ void fail_because_no_bike_brand() {
// When we call the createModel method with that bike brand
// Then the method should throw
assertThrows(NoSuchElementException.class,
- () -> relationalModelsService.createModel(input));
+ () -> modelsService.createModel(input));
}
@Test
@@ -88,7 +88,7 @@ void success() {
.thenReturn(expectedSavedModelEntity);
// When we call the createModel method with that input
- Model result = relationalModelsService.createModel(input);
+ Model result = modelsService.createModel(input);
// Then we should have received the expected Model object
assertThat(result).isEqualTo(expectedSavedModelEntity.asModel());
@@ -106,7 +106,7 @@ void fail_because_no_model() {
// When we call the deleteModel method with that id
// Then the method should throw
assertThrows(NoSuchElementException.class,
- () -> relationalModelsService.deleteModel(ModelId.serialize(ghostModelId)));
+ () -> modelsService.deleteModel(ModelId.serialize(ghostModelId)));
}
@Test
@@ -117,7 +117,7 @@ void success() {
.thenReturn(Optional.of(EntityFactory.newModelEntityWithId(modelId)));
// When we call the deleteModel method with that id
- String result = relationalModelsService.deleteModel(ModelId.serialize(modelId));
+ String result = modelsService.deleteModel(ModelId.serialize(modelId));
// Then the repository should have been asked to delete the model
verify(mockModelRepository).deleteById(modelId);