UNITTEST ERA
Some checks failed
Build and Push Quarkus Image / build-and-push (push) Has been cancelled
Some checks failed
Build and Push Quarkus Image / build-and-push (push) Has been cancelled
This commit is contained in:
7
pom.xml
7
pom.xml
@@ -24,7 +24,7 @@
|
||||
<sonar.qualitygate.wait>true</sonar.qualitygate.wait>
|
||||
|
||||
<sonar.coverage.jacoco.xmlReportPaths>target/jacoco-report/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
|
||||
<sonar.coverage.exclusions>**/domain/**, **/config/**, **/*Exception.java, **/entity/**</sonar.coverage.exclusions>
|
||||
<sonar.coverage.exclusions>**/domain/**, **/config/**, **/*Exception.java, **/entity/**, **/test/java/**</sonar.coverage.exclusions>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -105,6 +105,11 @@
|
||||
<artifactId>quarkus-jacoco</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5-mockito</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -3,10 +3,8 @@ package nl.veenm.jobfindr.repository;
|
||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import nl.veenm.jobfindr.domain.Event;
|
||||
import nl.veenm.jobfindr.domain.VacatureDetail;
|
||||
|
||||
@ApplicationScoped
|
||||
public class EventRepository implements PanacheRepository<Event> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,5 @@ import nl.veenm.jobfindr.domain.VacatureDetail;
|
||||
|
||||
@ApplicationScoped
|
||||
public class VacatureDetailRepository implements PanacheRepository<VacatureDetail> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,15 +4,8 @@ import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import nl.veenm.jobfindr.domain.Vacature;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ApplicationScoped
|
||||
public class VacatureRepository implements PanacheRepository<Vacature> {
|
||||
|
||||
public List<Vacature> findByDate(LocalDate date) {
|
||||
return list("datum", date);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,13 @@ import java.util.List;
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class VacatureResource {
|
||||
private static final org.jboss.logging.Logger logger = Logger.getLogger(VacatureService.class);
|
||||
private static final org.jboss.logging.Logger logger = Logger.getLogger(VacatureResource.class);
|
||||
|
||||
@Inject
|
||||
public VacatureResource(VacatureService vacatureService) {
|
||||
this.vacatureService = vacatureService;
|
||||
}
|
||||
|
||||
VacatureService vacatureService;
|
||||
|
||||
@GET
|
||||
@@ -25,7 +29,7 @@ public class VacatureResource {
|
||||
return vacatureService.getNewVacatures();
|
||||
}
|
||||
|
||||
@GET
|
||||
@PATCH
|
||||
@Path("/test")
|
||||
public void testEmails(){
|
||||
logger.info("testEmails");
|
||||
|
||||
@@ -15,6 +15,11 @@ import java.util.List;
|
||||
public class EmailService {
|
||||
|
||||
@Inject
|
||||
public EmailService(Mailer mailer, EventService eventService) {
|
||||
this.mailer = mailer;
|
||||
this.eventService = eventService;
|
||||
}
|
||||
|
||||
EventService eventService;
|
||||
|
||||
private final String className = this.getClass().getSimpleName();
|
||||
@@ -23,11 +28,8 @@ public class EmailService {
|
||||
|
||||
private final Mailer mailer;
|
||||
|
||||
public EmailService(Mailer mailer) {
|
||||
this.mailer = mailer;
|
||||
}
|
||||
|
||||
public void stuurVacatureEmail(String recipient, List<Vacature> vacatures) {
|
||||
String methodName = "stuurVacatureEmail";
|
||||
// Bouw de HTML-inhoud van de e-mail
|
||||
StringBuilder emailBody = new StringBuilder();
|
||||
emailBody.append("<html>")
|
||||
@@ -76,12 +78,12 @@ public class EmailService {
|
||||
|
||||
// Verstuur de e-mail met HTML-inhoud
|
||||
log.info("Sending email to " + recipient);
|
||||
eventService.logInfo(className, "stuurVacatureEmail", "Sending email to " + recipient);
|
||||
eventService.logInfo(className, methodName, "Sending email to " + recipient);
|
||||
try{
|
||||
mailer.send(Mail.withHtml(recipient, subject, emailBody.toString()));
|
||||
eventService.logSucces(className, "stuurVacatureEmail", "Email sent");
|
||||
eventService.logSucces(className, methodName, "Email sent");
|
||||
} catch (Exception e) {
|
||||
eventService.logError(className, "stuurVacatureEmail", "Sending email failed", e);
|
||||
eventService.logError(className, methodName, "Sending email failed", e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,21 +18,25 @@ import java.util.List;
|
||||
|
||||
@ApplicationScoped
|
||||
public class VacatureService {
|
||||
@Inject
|
||||
ScraperService scraperService;
|
||||
|
||||
@Inject
|
||||
EventService eventService;
|
||||
|
||||
@Inject
|
||||
EmailService emailService;
|
||||
|
||||
@Inject
|
||||
VacatureRepository vacatureRepository;
|
||||
|
||||
@Inject
|
||||
VacatureDetailRepository vacatureDetailRepository;
|
||||
|
||||
@Inject
|
||||
public VacatureService(ScraperService scraperService, EventService eventService, EmailService emailService, VacatureRepository vacatureRepository, VacatureDetailRepository vacatureDetailRepository) {
|
||||
this.scraperService = scraperService;
|
||||
this.eventService = eventService;
|
||||
this.emailService = emailService;
|
||||
this.vacatureRepository = vacatureRepository;
|
||||
this.vacatureDetailRepository = vacatureDetailRepository;
|
||||
}
|
||||
|
||||
private static final Logger logger = Logger.getLogger(VacatureService.class);
|
||||
|
||||
private final String className = this.getClass().getSimpleName();
|
||||
@@ -46,8 +50,9 @@ public class VacatureService {
|
||||
|
||||
@Transactional
|
||||
public void checkAndSendNewVacatures() {
|
||||
String methodName = "checkAndSendNewVacatures";
|
||||
logger.info("Checking for new vacatures");
|
||||
eventService.logInfo(className, "checkAndSendNewVacatures", "Checking for new vacatures");
|
||||
eventService.logInfo(className, methodName, "Checking for new vacatures");
|
||||
LocalDate today = LocalDate.now();
|
||||
List<Vacature> todayVacatures = getVacatures();
|
||||
|
||||
@@ -55,7 +60,7 @@ public class VacatureService {
|
||||
try {
|
||||
scraperService.getVacatureDetails(todayVacature);
|
||||
} catch (IOException e) {
|
||||
eventService.logError(className, "checkAndSendNewVacatures", "checkAndSendNewVacatures failed", e);
|
||||
eventService.logError(className, methodName, "checkAndSendNewVacatures failed", e);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -76,10 +81,10 @@ public class VacatureService {
|
||||
emailService.stuurVacatureEmail("danthefranken@gmail.com", todayVacatures);
|
||||
emailService.stuurVacatureEmail("vanveenmel11@gmail.com", todayVacatures);
|
||||
logger.info("Nieuwe vacatures verstuurd en opgeslagen.");
|
||||
eventService.logSucces(className, "checkAndSendNewVacatures", "Nieuwe vacatures verstuurd en opgeslagen.");
|
||||
eventService.logSucces(className, methodName, "Nieuwe vacatures verstuurd en opgeslagen.");
|
||||
} else {
|
||||
logger.info("Geen nieuwe vacatures gevonden.");
|
||||
eventService.logInfo(className, "checkAndSendNewVacatures", "Geen nieuwe vacatures gevonden.");
|
||||
eventService.logInfo(className, methodName, "Geen nieuwe vacatures gevonden.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +100,7 @@ public class VacatureService {
|
||||
try {
|
||||
todayVacatures.addAll(scraperService.scrapeVacatures(url));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
eventService.logError(className, "getVacatures", "getVacatures failed", e);
|
||||
}
|
||||
});
|
||||
return todayVacatures;
|
||||
@@ -116,21 +121,22 @@ public class VacatureService {
|
||||
@Scheduled(cron = "0 0 0 * * ?")
|
||||
@Transactional
|
||||
public void cleanVacatures() {
|
||||
String methodName = "cleanVacatures";
|
||||
logger.info("Cleaning vacatures");
|
||||
eventService.logInfo(className, "cleanVacatures", "Cleaning vacatures");
|
||||
eventService.logInfo(className, methodName, "Cleaning vacatures");
|
||||
getAllVacatures().forEach(vacature -> {
|
||||
var date = vacature.getClosingDate();
|
||||
var today = LocalDate.now();
|
||||
|
||||
if (date.isBefore(today)) {
|
||||
logger.info("Deleting vacature " + vacature.getTitel());
|
||||
eventService.logInfo(className, "cleanVacatures", "Deleting vacature " + vacature.getTitel());
|
||||
eventService.logInfo(className, methodName, "Deleting vacature " + vacature.getTitel());
|
||||
vacatureDetailRepository.delete(vacature.getDetail());
|
||||
vacatureRepository.delete(vacature);
|
||||
}
|
||||
});
|
||||
logger.info("Cleaning vacatures done");
|
||||
eventService.logSucces(className, "cleanVacatures", "Cleaning vacatures done");
|
||||
eventService.logSucces(className, methodName, "Cleaning vacatures done");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ import java.time.Instant;
|
||||
public class EventService {
|
||||
|
||||
@Inject
|
||||
public EventService(EventRepository eventRepository) {
|
||||
this.eventRepository = eventRepository;
|
||||
}
|
||||
|
||||
EventRepository eventRepository;
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package nl.veenm.jobfindr.resources;
|
||||
|
||||
import nl.veenm.jobfindr.domain.Vacature;
|
||||
import nl.veenm.jobfindr.services.VacatureService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class VacatureResourceTest {
|
||||
|
||||
@Mock
|
||||
VacatureService vacatureService;
|
||||
|
||||
@InjectMocks
|
||||
VacatureResource vacatureResource;
|
||||
|
||||
@Test
|
||||
void getNewVacatures_ReturnsListFromService() {
|
||||
List<Vacature> expectedVacatures = List.of(new Vacature(), new Vacature());
|
||||
when(vacatureService.getNewVacatures()).thenReturn(expectedVacatures);
|
||||
|
||||
List<Vacature> result = vacatureResource.getNewVacatures();
|
||||
|
||||
assertEquals(2, result.size());
|
||||
assertEquals(expectedVacatures, result);
|
||||
verify(vacatureService).getNewVacatures();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmails_CallsCheckAndSendNewVacatures() {
|
||||
vacatureResource.testEmails();
|
||||
|
||||
verify(vacatureService).checkAndSendNewVacatures();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllVacatures_ReturnsListFromService() {
|
||||
List<Vacature> expectedVacatures = List.of(new Vacature());
|
||||
when(vacatureService.getAllVacatures()).thenReturn(expectedVacatures);
|
||||
|
||||
List<Vacature> result = vacatureResource.getAllVacatures();
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(expectedVacatures, result);
|
||||
verify(vacatureService).getAllVacatures();
|
||||
}
|
||||
|
||||
@Test
|
||||
void cleanVacatures_CallsCleanVacaturesOnService() {
|
||||
vacatureResource.cleanVacatures();
|
||||
|
||||
verify(vacatureService).cleanVacatures();
|
||||
}
|
||||
}
|
||||
103
src/test/java/nl/veenm/jobfindr/scrapers/ScraperServiceTest.java
Normal file
103
src/test/java/nl/veenm/jobfindr/scrapers/ScraperServiceTest.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package nl.veenm.jobfindr.scrapers;
|
||||
|
||||
import nl.veenm.jobfindr.domain.Vacature;
|
||||
import org.jsoup.Connection;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ScraperServiceTest {
|
||||
|
||||
@InjectMocks
|
||||
ScraperService scraperService;
|
||||
|
||||
@Test
|
||||
void getVacatureDetails_HaaltBeschrijvingEnDatumOp() throws IOException {
|
||||
String detailHtml = "<html><body>" +
|
||||
"<div class=\"rounded gray-tag-md px-2 py-2\">0,8 FTE</div>" +
|
||||
"<div class=\"rounded gray-tag-md px-2 py-2\">Sluitingsdatum: 15-04-2026</div>" +
|
||||
"</body></html>";
|
||||
Document mockDocument = Jsoup.parse(detailHtml);
|
||||
|
||||
Connection mockConnection = mock(Connection.class);
|
||||
when(mockConnection.get()).thenReturn(mockDocument);
|
||||
|
||||
Vacature vacature = new Vacature("Test", "https://fake-url.com", "Apeldoorn");
|
||||
|
||||
try (MockedStatic<Jsoup> mockedJsoup = mockStatic(Jsoup.class)) {
|
||||
mockedJsoup.when(() -> Jsoup.connect("https://fake-url.com")).thenReturn(mockConnection);
|
||||
|
||||
scraperService.getVacatureDetails(vacature);
|
||||
|
||||
assertEquals("0,8 FTE<br>Sluitingsdatum: 15-04-2026<br>", vacature.getDescription());
|
||||
assertEquals(LocalDate.of(2026, 4, 15), vacature.getClosingDate());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void scrapeVacatures_HaaltLijstOpEnFiltertOnbekendeLocaties() throws IOException {
|
||||
String listHtml = "<html><body>" +
|
||||
" <div>" +
|
||||
" <div class='mt-2 text-overflow-ellipsis'>" +
|
||||
" <div class='heading-6'>Docent Geschiedenis</div>" +
|
||||
" <a class='vacature-target' data-target='/split/vacature/123'>Link</a>" +
|
||||
" </div>" +
|
||||
" <div class='location mt-1'>Apeldoorn</div>" +
|
||||
" </div>" +
|
||||
" <div>" +
|
||||
" <div class='mt-2 text-overflow-ellipsis'>" +
|
||||
" <div class='heading-6'>Docent Wiskunde</div>" +
|
||||
" <a class='vacature-target' data-target='/vacature/456'>Link</a>" +
|
||||
" </div>" +
|
||||
" </div>" +
|
||||
"</body></html>";
|
||||
|
||||
String detailHtml = "<html><body><div class='rounded gray-tag-md px-2 py-2'>Sluitingsdatum: 01-05-2026</div></body></html>";
|
||||
String mainUrl = "https://www.meesterbaan.nl/zoeken";
|
||||
|
||||
// FIX: We parsen de HTML nu hier, buiten het bereik van de mock!
|
||||
Document listDocument = Jsoup.parse(listHtml);
|
||||
Document detailDocument = Jsoup.parse(detailHtml);
|
||||
|
||||
try (MockedStatic<Jsoup> mockedJsoup = mockStatic(Jsoup.class)) {
|
||||
mockedJsoup.when(() -> Jsoup.connect(anyString())).thenAnswer(invocation -> {
|
||||
String url = invocation.getArgument(0);
|
||||
Connection connection = mock(Connection.class);
|
||||
|
||||
// We geven nu direct de kant-en-klare Document objecten terug
|
||||
if (url.equals(mainUrl)) {
|
||||
when(connection.get()).thenReturn(listDocument);
|
||||
} else {
|
||||
when(connection.get()).thenReturn(detailDocument);
|
||||
}
|
||||
return connection;
|
||||
});
|
||||
|
||||
// Act
|
||||
List<Vacature> results = scraperService.scrapeVacatures(mainUrl);
|
||||
|
||||
// Assert
|
||||
assertEquals(1, results.size());
|
||||
|
||||
Vacature v = results.getFirst();
|
||||
assertEquals("Docent Geschiedenis", v.getTitel());
|
||||
assertEquals("https://www.meesterbaan.nl/vacature/123", v.getUrl());
|
||||
assertEquals("Apeldoorn", v.getLocatie());
|
||||
assertEquals("Sluitingsdatum: 01-05-2026<br>", v.getDescription());
|
||||
assertEquals(LocalDate.of(2026, 5, 1), v.getClosingDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package nl.veenm.jobfindr.services;
|
||||
|
||||
import io.quarkus.mailer.Mail;
|
||||
import io.quarkus.mailer.Mailer;
|
||||
import nl.veenm.jobfindr.domain.Vacature;
|
||||
import nl.veenm.jobfindr.util.EventService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class EmailServiceTest {
|
||||
|
||||
@Mock
|
||||
EventService eventService;
|
||||
|
||||
@Mock
|
||||
Mailer mailer;
|
||||
|
||||
@InjectMocks
|
||||
EmailService emailService;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<Mail> mailCaptor;
|
||||
|
||||
@Test
|
||||
void stuurVacatureEmail_VerstuurtEmailEnLogtSucces() {
|
||||
Vacature vacature = mock(Vacature.class);
|
||||
when(vacature.getTitel()).thenReturn("Java Developer");
|
||||
when(vacature.getDescription()).thenReturn("Mooie Quarkus rol");
|
||||
when(vacature.getUrl()).thenReturn("https://example.com/vacature/1");
|
||||
|
||||
emailService.stuurVacatureEmail("henk@example.com", List.of(vacature));
|
||||
|
||||
verify(eventService).logInfo("EmailService", "stuurVacatureEmail", "Sending email to henk@example.com");
|
||||
|
||||
verify(mailer).send(mailCaptor.capture());
|
||||
Mail capturedMail = mailCaptor.getValue();
|
||||
|
||||
assertEquals(1, capturedMail.getTo().size());
|
||||
assertEquals("henk@example.com", capturedMail.getTo().getFirst());
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String expectedDate = now.getDayOfMonth() + "-" + now.getMonthValue() + "-" + now.getYear();
|
||||
assertEquals("[" + expectedDate + "] Nieuwe vacatures gevonden", capturedMail.getSubject());
|
||||
|
||||
String htmlBody = capturedMail.getHtml();
|
||||
assertTrue(htmlBody.contains("Lieve Danthe"));
|
||||
assertTrue(htmlBody.contains("Java Developer"));
|
||||
assertTrue(htmlBody.contains("Mooie Quarkus rol"));
|
||||
assertTrue(htmlBody.contains("https://example.com/vacature/1"));
|
||||
|
||||
verify(eventService).logSucces("EmailService", "stuurVacatureEmail", "Email sent");
|
||||
}
|
||||
|
||||
@Test
|
||||
void stuurVacatureEmail_LogtErrorBijException() {
|
||||
RuntimeException exception = new RuntimeException("Mail server down");
|
||||
doThrow(exception).when(mailer).send(any(Mail.class));
|
||||
|
||||
emailService.stuurVacatureEmail("henk@example.com", List.of());
|
||||
|
||||
verify(eventService).logInfo("EmailService", "stuurVacatureEmail", "Sending email to henk@example.com");
|
||||
verify(eventService).logError("EmailService", "stuurVacatureEmail", "Sending email failed", exception);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package nl.veenm.jobfindr.services;
|
||||
|
||||
import io.quarkus.hibernate.orm.panache.PanacheQuery;
|
||||
import nl.veenm.jobfindr.domain.Vacature;
|
||||
import nl.veenm.jobfindr.domain.VacatureDetail;
|
||||
import nl.veenm.jobfindr.repository.VacatureDetailRepository;
|
||||
import nl.veenm.jobfindr.repository.VacatureRepository;
|
||||
import nl.veenm.jobfindr.scrapers.ScraperService;
|
||||
import nl.veenm.jobfindr.util.EventService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class VacatureServiceTest {
|
||||
|
||||
@Mock
|
||||
ScraperService scraperService;
|
||||
|
||||
@Mock
|
||||
EventService eventService;
|
||||
|
||||
@Mock
|
||||
EmailService emailService;
|
||||
|
||||
@Mock
|
||||
VacatureRepository vacatureRepository;
|
||||
|
||||
@Mock
|
||||
VacatureDetailRepository vacatureDetailRepository;
|
||||
|
||||
@InjectMocks
|
||||
VacatureService vacatureService;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<String> emailCaptor;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<List<Vacature>> listCaptor;
|
||||
|
||||
@Test
|
||||
void getNewVacatures() throws IOException {
|
||||
Vacature v1 = new Vacature();
|
||||
when(scraperService.scrapeVacatures(anyString())).thenReturn(List.of(v1));
|
||||
|
||||
List<Vacature> result = vacatureService.getNewVacatures();
|
||||
|
||||
assertEquals(2, result.size());
|
||||
|
||||
// Geen eq() nodig omdat we exacte waarden doorgeven zonder matchers
|
||||
verify(eventService).logInfo(VacatureService.class.getName(), "getServices", "getServices aangeroepen");
|
||||
|
||||
// Afvangen in plaats van eq()
|
||||
verify(emailService).stuurVacatureEmail(emailCaptor.capture(), listCaptor.capture());
|
||||
assertEquals("vanveenmel11@gmail.com", emailCaptor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void checkAndSendNewVacatures_WithNewVacatures() throws IOException {
|
||||
Vacature newVacature = new Vacature();
|
||||
newVacature.setUrl("url1");
|
||||
|
||||
Vacature existingVacature = new Vacature();
|
||||
existingVacature.setUrl("url2");
|
||||
|
||||
when(scraperService.scrapeVacatures(anyString())).thenReturn(List.of(newVacature, existingVacature));
|
||||
|
||||
PanacheQuery<Vacature> query = mock(PanacheQuery.class);
|
||||
when(vacatureRepository.findAll()).thenReturn(query);
|
||||
when(query.stream()).thenReturn(Stream.of(existingVacature));
|
||||
|
||||
vacatureService.checkAndSendNewVacatures();
|
||||
|
||||
verify(scraperService, times(4)).getVacatureDetails(any(Vacature.class));
|
||||
verify(vacatureRepository, times(2)).persist(any(Vacature.class));
|
||||
|
||||
verify(emailService, times(2)).stuurVacatureEmail(emailCaptor.capture(), listCaptor.capture());
|
||||
assertEquals("vanveenmel11@gmail.com", emailCaptor.getValue());
|
||||
|
||||
verify(eventService).logSucces("VacatureService", "checkAndSendNewVacatures", "Nieuwe vacatures verstuurd en opgeslagen.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void checkAndSendNewVacatures_NoNewVacatures() throws IOException {
|
||||
Vacature existingVacature = new Vacature();
|
||||
existingVacature.setUrl("url1");
|
||||
|
||||
when(scraperService.scrapeVacatures(anyString())).thenReturn(List.of(existingVacature));
|
||||
|
||||
PanacheQuery<Vacature> query = mock(PanacheQuery.class);
|
||||
when(vacatureRepository.findAll()).thenReturn(query);
|
||||
when(query.stream()).thenReturn(Stream.of(existingVacature));
|
||||
|
||||
vacatureService.checkAndSendNewVacatures();
|
||||
|
||||
verify(vacatureRepository, never()).persist(any(Vacature.class));
|
||||
// Omdat het nooit wordt aangeroepen, kunnen we hier wel any() en anyString() gebruiken
|
||||
verify(emailService, never()).stuurVacatureEmail(anyString(), any());
|
||||
|
||||
verify(eventService).logInfo("VacatureService", "checkAndSendNewVacatures", "Geen nieuwe vacatures gevonden.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void checkAndSendNewVacatures_HandlesIOException() throws IOException {
|
||||
Vacature vacature = new Vacature();
|
||||
vacature.setUrl("url1");
|
||||
|
||||
when(scraperService.scrapeVacatures(anyString())).thenReturn(List.of(vacature));
|
||||
|
||||
IOException exception = new IOException("Scrape failed");
|
||||
doThrow(exception).when(scraperService).getVacatureDetails(any(Vacature.class));
|
||||
|
||||
PanacheQuery<Vacature> query = mock(PanacheQuery.class);
|
||||
when(vacatureRepository.findAll()).thenReturn(query);
|
||||
when(query.stream()).thenReturn(Stream.empty());
|
||||
|
||||
vacatureService.checkAndSendNewVacatures();
|
||||
|
||||
// Pass the actual exception object directly
|
||||
verify(eventService, times(2)).logError("VacatureService", "checkAndSendNewVacatures", "checkAndSendNewVacatures failed", exception);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAllVacatures() {
|
||||
List<Vacature> vacatures = List.of(new Vacature());
|
||||
when(vacatureRepository.listAll()).thenReturn(vacatures);
|
||||
|
||||
List<Vacature> result = vacatureService.getAllVacatures();
|
||||
|
||||
assertEquals(1, result.size());
|
||||
verify(eventService).logInfo("VacatureService", "getAllVacatures", "fetching all vacatures");
|
||||
}
|
||||
|
||||
@Test
|
||||
void cleanVacatures() {
|
||||
Vacature expired = new Vacature();
|
||||
expired.setTitel("Oude Vacature");
|
||||
expired.setClosingDate(LocalDate.now().minusDays(1));
|
||||
VacatureDetail detail = mock(VacatureDetail.class);
|
||||
expired.setDetail(detail);
|
||||
|
||||
Vacature valid = new Vacature();
|
||||
valid.setClosingDate(LocalDate.now().plusDays(1));
|
||||
|
||||
when(vacatureRepository.listAll()).thenReturn(List.of(expired, valid));
|
||||
|
||||
vacatureService.cleanVacatures();
|
||||
|
||||
verify(vacatureDetailRepository).delete(detail);
|
||||
verify(vacatureRepository).delete(expired);
|
||||
verify(vacatureRepository, never()).delete(valid);
|
||||
|
||||
verify(eventService).logSucces("VacatureService", "cleanVacatures", "Cleaning vacatures done");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void dagelijksControleerEnVerstuur() {
|
||||
PanacheQuery<Vacature> query = mock(PanacheQuery.class);
|
||||
when(vacatureRepository.findAll()).thenReturn(query);
|
||||
when(query.stream()).thenReturn(Stream.empty());
|
||||
|
||||
vacatureService.dagelijksControleerEnVerstuur();
|
||||
|
||||
verify(eventService).logInfo("VacatureService", "checkAndSendNewVacatures", "Checking for new vacatures");
|
||||
}
|
||||
}
|
||||
80
src/test/java/nl/veenm/jobfindr/util/EventServiceTest.java
Normal file
80
src/test/java/nl/veenm/jobfindr/util/EventServiceTest.java
Normal file
@@ -0,0 +1,80 @@
|
||||
package nl.veenm.jobfindr.util;
|
||||
|
||||
import nl.veenm.jobfindr.domain.Event;
|
||||
import nl.veenm.jobfindr.repository.EventRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class EventServiceTest {
|
||||
|
||||
@Mock
|
||||
EventRepository eventRepository;
|
||||
|
||||
@InjectMocks
|
||||
EventService eventService;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<Event> eventCaptor;
|
||||
|
||||
@Test
|
||||
void testLogInfo_SavesInfoEvent() {
|
||||
eventService.logInfo("MyClass", "myMethod", "Dit is een info bericht");
|
||||
|
||||
verify(eventRepository).persist(eventCaptor.capture());
|
||||
Event capturedEvent = eventCaptor.getValue();
|
||||
|
||||
assertNotNull(capturedEvent.getTimestamp());
|
||||
assertEquals("MyClass", capturedEvent.getClassName());
|
||||
assertEquals("myMethod", capturedEvent.getMethodName());
|
||||
assertEquals("Dit is een info bericht", capturedEvent.getMessage());
|
||||
assertEquals("INFO", capturedEvent.getLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLogSucces_SavesSuccessEvent() {
|
||||
eventService.logSucces("MyClass", "myMethod", "Dit is gelukt");
|
||||
|
||||
verify(eventRepository).persist(eventCaptor.capture());
|
||||
Event capturedEvent = eventCaptor.getValue();
|
||||
|
||||
assertNotNull(capturedEvent.getTimestamp());
|
||||
assertEquals("MyClass", capturedEvent.getClassName());
|
||||
assertEquals("myMethod", capturedEvent.getMethodName());
|
||||
assertEquals("Dit is gelukt", capturedEvent.getMessage());
|
||||
assertEquals("SUCCESS", capturedEvent.getLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLogError_SavesErrorEventWithExceptionMessage() {
|
||||
Exception dummyException = new RuntimeException("Database connectie verbroken");
|
||||
|
||||
eventService.logError("MyClass", "myMethod", "Er ging iets mis", dummyException);
|
||||
|
||||
verify(eventRepository).persist(eventCaptor.capture());
|
||||
Event capturedEvent = eventCaptor.getValue();
|
||||
|
||||
assertNotNull(capturedEvent.getTimestamp());
|
||||
assertEquals("MyClass", capturedEvent.getClassName());
|
||||
assertEquals("myMethod", capturedEvent.getMethodName());
|
||||
assertEquals("Er ging iets mis", capturedEvent.getMessage());
|
||||
assertEquals("ERROR", capturedEvent.getLevel());
|
||||
assertEquals("Database connectie verbroken", capturedEvent.getError());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCleanEvents_CallsDeleteAll() {
|
||||
eventService.cleanEvents();
|
||||
|
||||
verify(eventRepository).deleteAll();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user