From d29b39b5ce5d4237d99ba90ef369d8b8b2eee3ab Mon Sep 17 00:00:00 2001 From: Martin Mladenov Date: Wed, 8 May 2024 15:36:23 +0200 Subject: [PATCH 1/4] Add mockito-junit-jupiter package to support @ExtendWith(MockitoExtension.class) --- andy/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/andy/pom.xml b/andy/pom.xml index 070c9b58..9699932a 100644 --- a/andy/pom.xml +++ b/andy/pom.xml @@ -78,6 +78,13 @@ ${mockito.version} + + + org.mockito + mockito-junit-jupiter + ${mockito.version} + + From 4d39350f83436be1573f3cba43f4c345dbf68a53 Mon Sep 17 00:00:00 2001 From: Martin Mladenov Date: Wed, 8 May 2024 15:36:50 +0200 Subject: [PATCH 2/4] Add tests for mocks with annotations --- .../test/java/integration/CodeChecksTest.java | 11 ++ .../test/java/integration/JUnitTestsTest.java | 18 +++ .../SoftWhereTestsWithAnnotation.java | 127 +++++++++++++++++ ...oftWhereTestsWithAnnotationExtendWith.java | 131 ++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotation.java create mode 100644 andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotationExtendWith.java diff --git a/andy/src/test/java/integration/CodeChecksTest.java b/andy/src/test/java/integration/CodeChecksTest.java index 39d285d1..d0d01e2a 100644 --- a/andy/src/test/java/integration/CodeChecksTest.java +++ b/andy/src/test/java/integration/CodeChecksTest.java @@ -20,6 +20,17 @@ void allChecksPass() { .has(codeCheck("getTripById should be set up", true, 1)); } + @Test + void mockChecksWithAnnotationPass() { + Result result = run( "SoftWhereLibrary", "SoftWhereTestsWithAnnotation", "SoftWhereConfigWithCodeChecksConfiguration"); + + assertThat(result) + .has(checksScore(3,3)) + .has(codeCheck("Trip Repository should be mocked", true, 1)) + .has(codeCheck("Trip should not be mocked", true, 1)) + .has(codeCheck("getTripById should be set up", true, 1)); + } + @Test void someChecksFail() { Result result = run( "SoftWhereLibrary", "SoftWhereTests", "SoftWhereConfigWithCodeChecks2Configuration"); diff --git a/andy/src/test/java/integration/JUnitTestsTest.java b/andy/src/test/java/integration/JUnitTestsTest.java index 7be11e6c..1df3475f 100644 --- a/andy/src/test/java/integration/JUnitTestsTest.java +++ b/andy/src/test/java/integration/JUnitTestsTest.java @@ -91,6 +91,24 @@ void mocksWork() { assertThat(result.getTests().hasTestsFailingOrFailures()).isFalse(); } + @Test + void mocksWithAnnotationWork() { + Result result = run(Action.TESTS, "SoftWhereLibrary", "SoftWhereTestsWithAnnotation"); + + assertThat(result.getTests().getTestsSucceeded()).isEqualTo(3); + assertThat(result.getTests().getTestsRan()).isEqualTo(3); + assertThat(result.getTests().hasTestsFailingOrFailures()).isFalse(); + } + + @Test + void mocksWithAnnotationExtendWithWork() { + Result result = run(Action.TESTS, "SoftWhereLibrary", "SoftWhereTestsWithAnnotationExtendWith"); + + assertThat(result.getTests().getTestsSucceeded()).isEqualTo(3); + assertThat(result.getTests().getTestsRan()).isEqualTo(3); + assertThat(result.getTests().hasTestsFailingOrFailures()).isFalse(); + } + } diff --git a/andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotation.java b/andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotation.java new file mode 100644 index 00000000..fbf0dfcc --- /dev/null +++ b/andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotation.java @@ -0,0 +1,127 @@ +package delft; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.time.LocalDate; +import java.util.*; +import java.util.stream.*; +import org.junit.jupiter.api.*; +import org.mockito.*; + + +class SoftWhereTests { + + //Methods have setup inside them, since I cannot use @BeforeEach and am + //not sure if if I write a separate method to setup this will work, so yeah + //there is a ton of code duplication to make sure grading will + //work as expected. I also need to not have any dependency between tests, + //so I cannot depend on one test making the setup. I will also not risk + //putting setup into lines 26-32 without a method because I have no clue + //what your grading system does and if it would work. + //I have just chosen the safest way. + + @Mock + ReservationRepository reservationRepository; + + @Mock + TripRepository tripRepository; + + SoftWhere softwhere; + Person person1, person2, person3, person4, person5, person6; + + Trip trip1, trip2, trip3; + Info info1, info2, info3; + + Reservation res1, res2, res3, res4; + + //test when it is possible to register for the given trip + @Test + void testPossibleToRegister() { + MockitoAnnotations.openMocks(this); + + + softwhere = new SoftWhere(tripRepository, reservationRepository); + + person1 = new Person("fname1", "mname1", "lname1", LocalDate.of(1998, 2, 5)); + person4 = new Person("fname4", "mname4", "lname4", LocalDate.of(1995, 11, 17)); + person5 = new Person("fname5", "mname5", "lname5", LocalDate.of(1978, 1, 1)); + info2 = new Info(LocalDate.of(2021, 7, 1), LocalDate.of(2021, 7, 15), Destination.MALTA); + trip2 = new Trip("Trip to Malta", info2, 2050, 3); + res4 = new Reservation(trip2, new ArrayList<>(List.of(person4, person5))); + + when(tripRepository.getTripById(2L)).thenReturn(trip2); + when(reservationRepository.getAllReservationsByTrip(trip2)).thenReturn(new ArrayList<>(List.of(res4))); + + List people = new ArrayList<>(List.of(person1)); + + assertTrue(softwhere.makeReservation(2L, people)); + + verify(tripRepository, times(1)).getTripById(2L); + verify(reservationRepository, times(1)).getAllReservationsByTrip(trip2); + verify(reservationRepository, times(1)).save(new Reservation(trip2, people)); + + verifyNoMoreInteractions(tripRepository); + verifyNoMoreInteractions(reservationRepository); + } + + //test when it is impossible to make a reservation + //as there are not enough places left + @Test + void testNotEnoughPlacesLeft() { + reservationRepository = mock(ReservationRepository.class); + tripRepository = mock(TripRepository.class); + + softwhere = new SoftWhere(tripRepository, reservationRepository); + + person3 = new Person("fname3", "mname3", "lname3", LocalDate.of(1998, 11, 17)); + person4 = new Person("fname4", "mname4", "lname4", LocalDate.of(1995, 11, 17)); + + person1 = new Person("fname1", "mname1", "lname1", LocalDate.of(1998, 2, 5)); + person2 = new Person("fname2", "mname2", "lname2", LocalDate.of(2001, 4, 3)); + person5 = new Person("fname5", "mname5", "lname5", LocalDate.of(1978, 1, 1)); + person6 = new Person("fname6", "mname6", "lname6", LocalDate.of(2004, 10, 4)); + info1 = new Info(LocalDate.of(2021, 6, 24), LocalDate.of(2021, 6, 30), Destination.GREECE); + trip1 = new Trip("Trip to Greece", info1, 1999, 5); + res1 = new Reservation(trip1, new ArrayList<>(List.of(person1, person2))); + res2 = new Reservation(trip1, new ArrayList<>(List.of(person5, person6))); + + when(tripRepository.getTripById(1L)).thenReturn(trip1); + when(reservationRepository.getAllReservationsByTrip(trip1)).thenReturn(new ArrayList<>(List.of(res1, res2))); + + List people = new ArrayList<>(List.of(person3, person4)); + + assertFalse(softwhere.makeReservation(1L, people)); + + verify(tripRepository, times(1)).getTripById(1L); + verify(reservationRepository, times(1)).getAllReservationsByTrip(trip1); + + verifyNoMoreInteractions(tripRepository); + verifyNoMoreInteractions(reservationRepository); + } + + //test when the wanted trip does not exist + @Test + void testNonexistentTrip() { + reservationRepository = mock(ReservationRepository.class); + tripRepository = mock(TripRepository.class); + + softwhere = new SoftWhere(tripRepository, reservationRepository); + + person3 = new Person("fname3", "mname3", "lname3", LocalDate.of(1998, 11, 17)); + + when(tripRepository.getTripById(4L)).thenThrow(new ElementNotFoundException()); + + List people = new ArrayList<>(List.of(person3)); + + assertFalse(softwhere.makeReservation(4L, people)); + + verify(tripRepository, times(1)).getTripById(4L); + + verifyNoMoreInteractions(tripRepository); + verifyNoMoreInteractions(reservationRepository); + } +} + diff --git a/andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotationExtendWith.java b/andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotationExtendWith.java new file mode 100644 index 00000000..20475a0c --- /dev/null +++ b/andy/src/test/resources/grader/fixtures/Solution/SoftWhereTestsWithAnnotationExtendWith.java @@ -0,0 +1,131 @@ +package delft; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.time.LocalDate; +import java.util.*; +import java.util.stream.*; +import org.junit.jupiter.api.*; +import org.mockito.*; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + + +@ExtendWith(MockitoExtension.class) +class SoftWhereTests { + + //Methods have setup inside them, since I cannot use @BeforeEach and am + //not sure if if I write a separate method to setup this will work, so yeah + //there is a ton of code duplication to make sure grading will + //work as expected. I also need to not have any dependency between tests, + //so I cannot depend on one test making the setup. I will also not risk + //putting setup into lines 26-32 without a method because I have no clue + //what your grading system does and if it would work. + //I have just chosen the safest way. + + @Mock + ReservationRepository reservationRepository; + + @Mock + TripRepository tripRepository; + + SoftWhere softwhere; + Person person1, person2, person3, person4, person5, person6; + + Trip trip1, trip2, trip3; + Info info1, info2, info3; + + Reservation res1, res2, res3, res4; + + //test when it is possible to register for the given trip + @Test + void testPossibleToRegister() { + MockitoAnnotations.openMocks(this); + + + softwhere = new SoftWhere(tripRepository, reservationRepository); + + person1 = new Person("fname1", "mname1", "lname1", LocalDate.of(1998, 2, 5)); + person4 = new Person("fname4", "mname4", "lname4", LocalDate.of(1995, 11, 17)); + person5 = new Person("fname5", "mname5", "lname5", LocalDate.of(1978, 1, 1)); + info2 = new Info(LocalDate.of(2021, 7, 1), LocalDate.of(2021, 7, 15), Destination.MALTA); + trip2 = new Trip("Trip to Malta", info2, 2050, 3); + res4 = new Reservation(trip2, new ArrayList<>(List.of(person4, person5))); + + when(tripRepository.getTripById(2L)).thenReturn(trip2); + when(reservationRepository.getAllReservationsByTrip(trip2)).thenReturn(new ArrayList<>(List.of(res4))); + + List people = new ArrayList<>(List.of(person1)); + + assertTrue(softwhere.makeReservation(2L, people)); + + verify(tripRepository, times(1)).getTripById(2L); + verify(reservationRepository, times(1)).getAllReservationsByTrip(trip2); + verify(reservationRepository, times(1)).save(new Reservation(trip2, people)); + + verifyNoMoreInteractions(tripRepository); + verifyNoMoreInteractions(reservationRepository); + } + + //test when it is impossible to make a reservation + //as there are not enough places left + @Test + void testNotEnoughPlacesLeft() { + reservationRepository = mock(ReservationRepository.class); + tripRepository = mock(TripRepository.class); + + softwhere = new SoftWhere(tripRepository, reservationRepository); + + person3 = new Person("fname3", "mname3", "lname3", LocalDate.of(1998, 11, 17)); + person4 = new Person("fname4", "mname4", "lname4", LocalDate.of(1995, 11, 17)); + + person1 = new Person("fname1", "mname1", "lname1", LocalDate.of(1998, 2, 5)); + person2 = new Person("fname2", "mname2", "lname2", LocalDate.of(2001, 4, 3)); + person5 = new Person("fname5", "mname5", "lname5", LocalDate.of(1978, 1, 1)); + person6 = new Person("fname6", "mname6", "lname6", LocalDate.of(2004, 10, 4)); + info1 = new Info(LocalDate.of(2021, 6, 24), LocalDate.of(2021, 6, 30), Destination.GREECE); + trip1 = new Trip("Trip to Greece", info1, 1999, 5); + res1 = new Reservation(trip1, new ArrayList<>(List.of(person1, person2))); + res2 = new Reservation(trip1, new ArrayList<>(List.of(person5, person6))); + + when(tripRepository.getTripById(1L)).thenReturn(trip1); + when(reservationRepository.getAllReservationsByTrip(trip1)).thenReturn(new ArrayList<>(List.of(res1, res2))); + + List people = new ArrayList<>(List.of(person3, person4)); + + assertFalse(softwhere.makeReservation(1L, people)); + + verify(tripRepository, times(1)).getTripById(1L); + verify(reservationRepository, times(1)).getAllReservationsByTrip(trip1); + + verifyNoMoreInteractions(tripRepository); + verifyNoMoreInteractions(reservationRepository); + } + + //test when the wanted trip does not exist + @Test + void testNonexistentTrip() { + reservationRepository = mock(ReservationRepository.class); + tripRepository = mock(TripRepository.class); + + softwhere = new SoftWhere(tripRepository, reservationRepository); + + person3 = new Person("fname3", "mname3", "lname3", LocalDate.of(1998, 11, 17)); + + when(tripRepository.getTripById(4L)).thenThrow(new ElementNotFoundException()); + + List people = new ArrayList<>(List.of(person3)); + + assertFalse(softwhere.makeReservation(4L, people)); + + verify(tripRepository, times(1)).getTripById(4L); + + verifyNoMoreInteractions(tripRepository); + verifyNoMoreInteractions(reservationRepository); + } +} + From 3c161018d3093d52f44ed88b44f69b97477d68dd Mon Sep 17 00:00:00 2001 From: Martin Mladenov Date: Wed, 8 May 2024 15:56:38 +0200 Subject: [PATCH 3/4] Fix bug in @Mock --- .../nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java b/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java index fb07b00a..2089e581 100644 --- a/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java +++ b/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java @@ -51,8 +51,8 @@ public boolean visit(FieldDeclaration fd) { // If the field is annotated with @Mock, check if it's the class we are interested in if (hasMockAnnotation) { - String className = fd.getType().toString(); - classWasMocked = className.contains(classToBeMocked); + String className = fd.getType().resolveBinding().getName(); + classWasMocked = className.equals(classToBeMocked); } } return super.visit(fd); From ff50248294fc51d839048cc5bfa97133a5b97aa6 Mon Sep 17 00:00:00 2001 From: Martin Mladenov Date: Wed, 8 May 2024 16:15:36 +0200 Subject: [PATCH 4/4] Fix issue with generics --- .../tudelft/cse1110/andy/codechecker/checks/MockClass.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java b/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java index 2089e581..5bd26660 100644 --- a/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java +++ b/andy/src/main/java/nl/tudelft/cse1110/andy/codechecker/checks/MockClass.java @@ -51,8 +51,9 @@ public boolean visit(FieldDeclaration fd) { // If the field is annotated with @Mock, check if it's the class we are interested in if (hasMockAnnotation) { - String className = fd.getType().resolveBinding().getName(); - classWasMocked = className.equals(classToBeMocked); + String className = fd.getType().resolveBinding().getBinaryName(); + String simpleName = className.substring(className.lastIndexOf('.') + 1); + classWasMocked = simpleName.equals(classToBeMocked); } } return super.visit(fd);