tests
This commit is contained in:
@@ -10,3 +10,5 @@ Here are some references and links which were used for this application:
|
||||
- Interesting question also involving academic domain
|
||||
|
||||
2. [Transactional, roll back transaction manually](https://stackoverflow.com/a/23502214)
|
||||
|
||||
3. [Baeldung, Jackson ignore null fields](https://www.baeldung.com/jackson-ignore-null-fields)
|
||||
@@ -6,4 +6,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
public interface CourseEntityRepository extends JpaRepository<CourseEntity, Integer> {
|
||||
|
||||
boolean existsCourseEntityByTitleLike(String title);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.cleanddd.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
// omit null fields from: https://www.baeldung.com/jackson-ignore-null-fields
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class CreateCourseResponse {
|
||||
|
||||
Boolean existsAlready;
|
||||
Integer courseId;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.cleanddd.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class CreateStudentResponse {
|
||||
|
||||
Boolean existsAlready;
|
||||
Integer studentId;
|
||||
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.github.cleanddd.usecase;
|
||||
|
||||
import com.github.cleanddd.dto.CreateCourseResponse;
|
||||
import com.github.cleanddd.dto.CreateStudentResponse;
|
||||
import com.github.cleanddd.model.Course;
|
||||
import com.github.cleanddd.model.EnrollResult;
|
||||
import com.github.cleanddd.model.Student;
|
||||
@@ -25,13 +27,16 @@ public class EnrollStudentUseCase implements EnrollStudentInputPort {
|
||||
public void createCourse(String title) {
|
||||
|
||||
if (persistenceOps.courseExistsWithTitle(title)) {
|
||||
restPresenter.presentOk(Map.of("exists", "already"));
|
||||
restPresenter.presentOk(CreateCourseResponse.builder().existsAlready(true));
|
||||
} else {
|
||||
final Integer courseId = persistenceOps.persist(Course.builder()
|
||||
.title(title)
|
||||
.build());
|
||||
|
||||
restPresenter.presentOk(Map.of("courseId", courseId));
|
||||
restPresenter.presentOk(CreateCourseResponse.builder()
|
||||
.existsAlready(false)
|
||||
.courseId(courseId)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,15 +44,16 @@ public class EnrollStudentUseCase implements EnrollStudentInputPort {
|
||||
@Transactional
|
||||
public void createStudent(String fullName) {
|
||||
|
||||
if (persistenceOps.studentExistsWithFullName(fullName)){
|
||||
restPresenter.presentOk(Map.of("exists", "already"));
|
||||
}
|
||||
else {
|
||||
if (persistenceOps.studentExistsWithFullName(fullName)) {
|
||||
restPresenter.presentOk(CreateStudentResponse.builder().existsAlready(true).build());
|
||||
} else {
|
||||
final Integer studentId = persistenceOps.persist(Student.builder()
|
||||
.fullName(fullName)
|
||||
.build());
|
||||
|
||||
restPresenter.presentOk(Map.of("studentId", studentId));
|
||||
restPresenter.presentOk(CreateStudentResponse.builder().existsAlready(false)
|
||||
.studentId(studentId)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,9 +77,7 @@ public class EnrollStudentUseCase implements EnrollStudentInputPort {
|
||||
}
|
||||
|
||||
// present the result of enrollment
|
||||
restPresenter.presentOk(Map.of("studentId", studentId,
|
||||
"newEnrollment", enrollResult.isCourseAdded(),
|
||||
"coursesIds", enrollResult.getStudent().getCoursesIds()));
|
||||
restPresenter.presentOk(enrollResult);
|
||||
} catch (Exception e) {
|
||||
restPresenter.presentError(e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.github.cleanddd.usecase;
|
||||
|
||||
import com.github.cleanddd.model.Course;
|
||||
import com.github.cleanddd.model.EnrollResult;
|
||||
import com.github.cleanddd.model.Student;
|
||||
import com.github.cleanddd.port.PersistenceOperationsOutputPort;
|
||||
import com.github.cleanddd.port.RestPresenterOutputPort;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class EnrollStudentUseCaseTest {
|
||||
|
||||
@Mock
|
||||
private RestPresenterOutputPort presenter;
|
||||
|
||||
@Mock
|
||||
private PersistenceOperationsOutputPort persistenceOps;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
||||
// return a mock course when asked to obtain one
|
||||
lenient().when(persistenceOps.obtainCourseById(anyInt()))
|
||||
.thenAnswer(invocation -> Course.builder()
|
||||
.id(invocation.getArgument(0))
|
||||
.title("Software architecture 101")
|
||||
.build());
|
||||
|
||||
// return a mock student enrolled in some courses when asked to obtain one
|
||||
lenient().when(persistenceOps.obtainStudentById(anyInt()))
|
||||
.thenAnswer(invocation -> Student.builder()
|
||||
.id(invocation.getArgument(0))
|
||||
.fullName("Brad Pitt")
|
||||
.coursesIds(Set.of(1, 2, 3))
|
||||
.build());
|
||||
|
||||
// just return the ID a course or a student when asked to
|
||||
// persist it
|
||||
lenient().when(persistenceOps.persist(any(Course.class)))
|
||||
.thenAnswer(invocation -> ((Course) invocation.getArgument(0)).getId());
|
||||
|
||||
lenient().when(persistenceOps.persist(any(Student.class)))
|
||||
.thenAnswer(invocation -> ((Student) invocation.getArgument(0)).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEnroll_StudentCanEnrollInCourseSheIsNotYetEnrolledIn() {
|
||||
|
||||
final EnrollStudentUseCase useCase = new EnrollStudentUseCase(presenter, persistenceOps);
|
||||
|
||||
// enroll student in a new course
|
||||
useCase.enroll(4, 1);
|
||||
assertNoError();
|
||||
|
||||
// verify the result of enrollment
|
||||
final ArgumentCaptor<EnrollResult> resultArg = ArgumentCaptor.forClass(EnrollResult.class);
|
||||
verify(presenter, times(1))
|
||||
.presentOk(resultArg.capture());
|
||||
|
||||
final EnrollResult enrollResult = resultArg.getValue();
|
||||
Assertions.assertThat(enrollResult.isCourseAdded()).isTrue();
|
||||
Assertions.assertThat(enrollResult.getStudent().getCoursesIds())
|
||||
.containsOnly(1,2,3,4);
|
||||
}
|
||||
|
||||
private void assertNoError() {
|
||||
verify(presenter, times(0)).presentError(any(Throwable.class));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user