From 3ad3e1883c73e3a2f541b2fd259b5b7182d89021 Mon Sep 17 00:00:00 2001 From: Colin DAMON <cdamon@ippon.fr> Date: Wed, 26 Aug 2020 08:09:02 +0200 Subject: [PATCH] First live content First simple versions of the activity domain Secondary ports exists but they need their adapters --- borestop/README.md | 8 +-- .../borestop/activity/domain/Activities.java | 19 +++++++ .../borestop/activity/domain/Activity.java | 25 +++++++++ .../borestop/activity/domain/Category.java | 5 ++ .../ippon/borestop/activity/domain/Idea.java | 24 +++++++++ .../activity/domain/IdeasRepository.java | 5 ++ .../borestop/activity/domain/Partner.java | 49 ++++++++++++++++++ .../borestop/activity/domain/Partners.java | 40 +++++++++++++++ .../activity/domain/PartnersRepository.java | 5 ++ .../secondary/RestIdeasRepository.java | 15 ++++++ .../activity/domain/ActivitiesUnitTest.java | 41 +++++++++++++++ .../activity/domain/ActivityUnitTest.java | 51 +++++++++++++++++++ .../activity/domain/IdeaUnitTest.java | 30 +++++++++++ .../activity/domain/IdeasFixture.java | 14 +++++ .../activity/domain/PartnerUnitTest.java | 42 +++++++++++++++ .../activity/domain/PartnersFixture.java | 22 ++++++++ .../activity/domain/PartnersUnitTest.java | 13 +++++ 17 files changed, 405 insertions(+), 3 deletions(-) create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/Activities.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/Activity.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/Category.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/Idea.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/IdeasRepository.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/Partner.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/Partners.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/domain/PartnersRepository.java create mode 100644 borestop/src/main/java/com/ippon/borestop/activity/infrastructure/secondary/RestIdeasRepository.java create mode 100644 borestop/src/test/java/com/ippon/borestop/activity/domain/ActivitiesUnitTest.java create mode 100644 borestop/src/test/java/com/ippon/borestop/activity/domain/ActivityUnitTest.java create mode 100644 borestop/src/test/java/com/ippon/borestop/activity/domain/IdeaUnitTest.java create mode 100644 borestop/src/test/java/com/ippon/borestop/activity/domain/IdeasFixture.java create mode 100644 borestop/src/test/java/com/ippon/borestop/activity/domain/PartnerUnitTest.java create mode 100644 borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersFixture.java create mode 100644 borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersUnitTest.java diff --git a/borestop/README.md b/borestop/README.md index d30802b8..29c3fde7 100644 --- a/borestop/README.md +++ b/borestop/README.md @@ -2,11 +2,13 @@ Création en live d'une application pour montrer l'apport de valeur pas différents niveaux de tests. +## Partie 1 + - **Auteurs** : Hippolyte DURIX && Colin DAMON - **Date** : 25/08/2020 - **Langage** : Java -- **Niveau** : Moyen -- **Replay** : //TODO +- **Niveau** : Débutant +- **Replay** : [La pyramide de tests de Kheops (partie 1) - Hippolyte et Colin](https://www.youtube.com/watch?v=rfRgJk251pw) ## JHipster @@ -54,7 +56,7 @@ The service worker initialization code is commented out by default. To enable it ```html <script> if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('./service-worker.js').then(function () { + navigator.serviceWorker.register('./service-worker.js').then(function() { console.log('Service Worker Registered'); }); } diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/Activities.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/Activities.java new file mode 100644 index 00000000..eeb451b8 --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/Activities.java @@ -0,0 +1,19 @@ +package com.ippon.borestop.activity.domain; + +public class Activities { + private final IdeasRepository ideas; + private final PartnersRepository partners; + + public Activities(IdeasRepository ideas, PartnersRepository partners) { + this.ideas = ideas; + this.partners = partners; + } + + public Activity next() { + Idea idea = ideas.next(); + + Partners matchingPartners = partners.find(idea.getCategory()); + + return new Activity(idea, matchingPartners); + } +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/Activity.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/Activity.java new file mode 100644 index 00000000..5a1d4d6f --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/Activity.java @@ -0,0 +1,25 @@ +package com.ippon.borestop.activity.domain; + +import com.ippon.borestop.common.domain.error.Assert; +import java.util.Collection; + +public class Activity { + private final Idea idea; + private final Partners partners; + + public Activity(Idea idea, Partners partners) { + Assert.notNull("idea", idea); + Assert.notNull("partners", partners); + + this.idea = idea; + this.partners = partners; + } + + public String getLabel() { + return idea.getLabel(); + } + + public Collection<Partner> getPartners() { + return partners.getPartners(); + } +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/Category.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/Category.java new file mode 100644 index 00000000..101af047 --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/Category.java @@ -0,0 +1,5 @@ +package com.ippon.borestop.activity.domain; + +public enum Category { + RELAXATION +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/Idea.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/Idea.java new file mode 100644 index 00000000..3c2ba1d8 --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/Idea.java @@ -0,0 +1,24 @@ +package com.ippon.borestop.activity.domain; + +import com.ippon.borestop.common.domain.error.Assert; + +public class Idea { + private final String label; + private final Category category; + + public Idea(String label, Category category) { + Assert.notBlank("label", label); + Assert.notNull("category", category); + + this.label = label; + this.category = category; + } + + public String getLabel() { + return label; + } + + public Category getCategory() { + return category; + } +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/IdeasRepository.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/IdeasRepository.java new file mode 100644 index 00000000..4ba2365c --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/IdeasRepository.java @@ -0,0 +1,5 @@ +package com.ippon.borestop.activity.domain; + +public interface IdeasRepository { + Idea next(); +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/Partner.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/Partner.java new file mode 100644 index 00000000..509fc49c --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/Partner.java @@ -0,0 +1,49 @@ +package com.ippon.borestop.activity.domain; + +import com.ippon.borestop.common.domain.error.Assert; + +public class Partner { + private final String name; + private final String website; + + private Partner(PartnerBuilder builder) { + Assert.notBlank("name", builder.name); + Assert.notBlank("website", builder.website); + + name = builder.name; + website = builder.website; + } + + public static PartnerBuilder builder() { + return new PartnerBuilder(); + } + + public String getName() { + return name; + } + + public String getWebsite() { + return website; + } + + public static class PartnerBuilder { + private String name; + private String website; + + public PartnerBuilder name(String name) { + this.name = name; + + return this; + } + + public PartnerBuilder website(String website) { + this.website = website; + + return this; + } + + public Partner build() { + return new Partner(this); + } + } +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/Partners.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/Partners.java new file mode 100644 index 00000000..7d1a7f69 --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/Partners.java @@ -0,0 +1,40 @@ +package com.ippon.borestop.activity.domain; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class Partners { + private final Collection<Partner> partners; + + private Partners(PartnersBuilder builder) { + partners = Collections.unmodifiableCollection(builder.partners); + } + + public static Partners empty() { + return builder().build(); + } + + public static PartnersBuilder builder() { + return new PartnersBuilder(); + } + + public Collection<Partner> getPartners() { + return partners; + } + + public static class PartnersBuilder { + private final List<Partner> partners = new ArrayList<>(); + + public PartnersBuilder add(Partner partner) { + partners.add(partner); + + return this; + } + + public Partners build() { + return new Partners(this); + } + } +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/domain/PartnersRepository.java b/borestop/src/main/java/com/ippon/borestop/activity/domain/PartnersRepository.java new file mode 100644 index 00000000..987519ee --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/domain/PartnersRepository.java @@ -0,0 +1,5 @@ +package com.ippon.borestop.activity.domain; + +public interface PartnersRepository { + Partners find(Category category); +} diff --git a/borestop/src/main/java/com/ippon/borestop/activity/infrastructure/secondary/RestIdeasRepository.java b/borestop/src/main/java/com/ippon/borestop/activity/infrastructure/secondary/RestIdeasRepository.java new file mode 100644 index 00000000..ff375789 --- /dev/null +++ b/borestop/src/main/java/com/ippon/borestop/activity/infrastructure/secondary/RestIdeasRepository.java @@ -0,0 +1,15 @@ +package com.ippon.borestop.activity.infrastructure.secondary; + +import com.ippon.borestop.activity.domain.Idea; +import com.ippon.borestop.activity.domain.IdeasRepository; +import org.springframework.stereotype.Service; + +@Service +class RestIdeasRepository implements IdeasRepository { + + @Override + public Idea next() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/borestop/src/test/java/com/ippon/borestop/activity/domain/ActivitiesUnitTest.java b/borestop/src/test/java/com/ippon/borestop/activity/domain/ActivitiesUnitTest.java new file mode 100644 index 00000000..285d1c6f --- /dev/null +++ b/borestop/src/test/java/com/ippon/borestop/activity/domain/ActivitiesUnitTest.java @@ -0,0 +1,41 @@ +package com.ippon.borestop.activity.domain; + +import static com.ippon.borestop.activity.domain.IdeasFixture.idea; +import static com.ippon.borestop.activity.domain.IdeasFixture.label; +import static com.ippon.borestop.activity.domain.PartnersFixture.firstPartner; +import static com.ippon.borestop.activity.domain.PartnersFixture.secondPartner; +import static com.ippon.borestop.activity.domain.PartnersFixture.thirdPartner; +import static com.ippon.borestop.activity.domain.PartnersFixture.threePartners; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +class ActivitiesUnitTest { + @Mock + private IdeasRepository ideas; + + @Mock + private PartnersRepository partners; + + @InjectMocks + private Activities activities; + + @Test + void shouldBuildActivity() { + when(ideas.next()).thenReturn(idea()); + when(partners.find(Category.RELAXATION)).thenReturn(threePartners()); + + Activity activity = activities.next(); + + assertThat(activity.getLabel()).isEqualTo(label()); + assertThat(activity.getPartners()) + .usingFieldByFieldElementComparator() + .containsExactly(firstPartner(), secondPartner(), thirdPartner()); + } +} diff --git a/borestop/src/test/java/com/ippon/borestop/activity/domain/ActivityUnitTest.java b/borestop/src/test/java/com/ippon/borestop/activity/domain/ActivityUnitTest.java new file mode 100644 index 00000000..bdcdaa12 --- /dev/null +++ b/borestop/src/test/java/com/ippon/borestop/activity/domain/ActivityUnitTest.java @@ -0,0 +1,51 @@ +package com.ippon.borestop.activity.domain; + +import static com.ippon.borestop.activity.domain.IdeasFixture.*; +import static com.ippon.borestop.activity.domain.PartnersFixture.*; +import static org.assertj.core.api.Assertions.*; + +import com.ippon.borestop.common.domain.error.MissingMandatoryValueException; +import org.junit.jupiter.api.Test; + +class ActivityUnitTest { + + @Test + void shouldNotBuildWithoutIdea() { + assertThatThrownBy(() -> new Activity(null, partners())) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("idea"); + } + + @Test + void shouldNotBuildWithoutPartners() { + assertThatThrownBy(() -> new Activity(idea(), null)) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("partners"); + } + + @Test + void shouldBuildActivityWithoutMatchingPartners() { + Activity activity = new Activity(idea(), emptyPartners()); + + assertThat(activity.getLabel()).isEqualTo(label()); + assertThat(activity.getPartners()).isEmpty(); + } + + @Test + void shouldBuildActivityWithThreePartnersInCategory() { + Activity activity = new Activity(idea(), threePartners()); + + assertThat(activity.getLabel()).isEqualTo(label()); + assertThat(activity.getPartners()) + .usingFieldByFieldElementComparator() + .containsExactly(firstPartner(), secondPartner(), thirdPartner()); + } + + private Partners partners() { + return threePartners(); + } + + private Partners emptyPartners() { + return Partners.empty(); + } +} diff --git a/borestop/src/test/java/com/ippon/borestop/activity/domain/IdeaUnitTest.java b/borestop/src/test/java/com/ippon/borestop/activity/domain/IdeaUnitTest.java new file mode 100644 index 00000000..bf94b71f --- /dev/null +++ b/borestop/src/test/java/com/ippon/borestop/activity/domain/IdeaUnitTest.java @@ -0,0 +1,30 @@ +package com.ippon.borestop.activity.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.ippon.borestop.common.domain.error.MissingMandatoryValueException; +import org.junit.jupiter.api.Test; + +class IdeaUnitTest { + + @Test + void shouldNotBuildWithoutLabel() { + assertThatThrownBy(() -> new Idea(null, Category.RELAXATION)) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("label"); + } + + @Test + void shouldNotBuildWithBlankLabel() { + assertThatThrownBy(() -> new Idea(" ", Category.RELAXATION)) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("label"); + } + + @Test + void shouldNotBuildWithoutCategory() { + assertThatThrownBy(() -> new Idea("label", null)) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("category"); + } +} diff --git a/borestop/src/test/java/com/ippon/borestop/activity/domain/IdeasFixture.java b/borestop/src/test/java/com/ippon/borestop/activity/domain/IdeasFixture.java new file mode 100644 index 00000000..f8ca164e --- /dev/null +++ b/borestop/src/test/java/com/ippon/borestop/activity/domain/IdeasFixture.java @@ -0,0 +1,14 @@ +package com.ippon.borestop.activity.domain; + +public final class IdeasFixture { + + private IdeasFixture() {} + + public static Idea idea() { + return new Idea(label(), Category.RELAXATION); + } + + public static String label() { + return "This is my idea"; + } +} diff --git a/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnerUnitTest.java b/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnerUnitTest.java new file mode 100644 index 00000000..1ac1851e --- /dev/null +++ b/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnerUnitTest.java @@ -0,0 +1,42 @@ +package com.ippon.borestop.activity.domain; + +import static org.assertj.core.api.Assertions.*; + +import com.ippon.borestop.activity.domain.Partner.PartnerBuilder; +import com.ippon.borestop.common.domain.error.MissingMandatoryValueException; +import org.junit.jupiter.api.Test; + +class PartnerUnitTest { + + @Test + void shouldNotBuildWithoutName() { + assertThatThrownBy(() -> fullBuilder().name(null).build()) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("name"); + } + + @Test + void shouldNotBuildWithBlankName() { + assertThatThrownBy(() -> fullBuilder().name(" ").build()) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("name"); + } + + @Test + void shouldNotBuildWithoutWebsite() { + assertThatThrownBy(() -> fullBuilder().website(null).build()) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("website"); + } + + @Test + void shouldNotBuildWithBlankWebsite() { + assertThatThrownBy(() -> fullBuilder().website(" ").build()) + .isExactlyInstanceOf(MissingMandatoryValueException.class) + .hasMessageContaining("website"); + } + + private PartnerBuilder fullBuilder() { + return Partner.builder().name("name").website("http://name"); + } +} diff --git a/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersFixture.java b/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersFixture.java new file mode 100644 index 00000000..b253194c --- /dev/null +++ b/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersFixture.java @@ -0,0 +1,22 @@ +package com.ippon.borestop.activity.domain; + +public final class PartnersFixture { + + private PartnersFixture() {} + + public static Partners threePartners() { + return Partners.builder().add(firstPartner()).add(secondPartner()).add(thirdPartner()).build(); + } + + public static Partner thirdPartner() { + return Partner.builder().name("third").website("http://third.com").build(); + } + + public static Partner secondPartner() { + return Partner.builder().name("second").website("http://second.com").build(); + } + + public static Partner firstPartner() { + return Partner.builder().name("name").website("http://name.com").build(); + } +} diff --git a/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersUnitTest.java b/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersUnitTest.java new file mode 100644 index 00000000..53a0c7d3 --- /dev/null +++ b/borestop/src/test/java/com/ippon/borestop/activity/domain/PartnersUnitTest.java @@ -0,0 +1,13 @@ +package com.ippon.borestop.activity.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; + +class PartnersUnitTest { + + @Test + void shouldNotBeAbleToUpdatePartners() { + assertThatThrownBy(() -> Partners.empty().getPartners().clear()).isExactlyInstanceOf(UnsupportedOperationException.class); + } +} -- GitLab