@nphumbert – @rnowif
Nadia & Renaud Humbert-Labeaumaz
@nphumbert – @rnowif
@nphumbert – @rnowif
Un code facilement testable doit
@nphumbert – @rnowif
public class FruitService {
public boolean isFruitPresentInBasket(Long basketId, Fruit fruit) {
return new FruitOracleDao()
.getFruitsByBasket(basketId)
.contains(fruit);
}
}
@nphumbert – @rnowif
@Test
public void should_find_fruit_in_basket() {
boolean fruitPresent = new FruitService()
.isFruitPresentInBasket(1L, aBanana());
// Impossible à vérifier sans vraie base de données Oracle !
assertThat(fruitPresent).isTrue();
}
@nphumbert – @rnowif
public class FruitService {
private final FruitRepository fruitRepository;
public FruitService(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
public boolean isFruitPresentInBasket(Long basketId, Fruit fruit) {
return fruitRepository
.getFruitsByBasket(basketId)
.contains(fruit);
}
}
@nphumbert – @rnowif
@Test
public void should_find_fruit_in_basket() {
FruitRepository fruitRepository = mock(FruitRepository.class);
when(fruitRepository.getFruitsByBasket(1L))
.thenReturn(asList(aBanana()));
boolean fruitPresent = new FruitService(fruitRepository)
.isFruitPresentInBasket(1L, aBanana());
assertThat(fruitPresent).isTrue();
}
@nphumbert – @rnowif
Rendre le code testable en isolation le rend
@nphumbert – @rnowif
public class FruitService {
public boolean isHealthy(FoodItem foodItem) {
Set<Vitamine> vitamines = emptySet();
if (foodItem instanceof Fruit) {
vitamines = newHashSet(A, B, C, E);
} else if (foodItem instanceof Dairy) {
vitamines = newHashSet(A, B, D);
} else if (foodItem instanceof Candy) {
vitamines = emptySet();
}
return vitamines.size() > 3;
}
}
@nphumbert – @rnowif
@Test
public void should_be_healthy_when_more_than_3_vitamines {
FoodItem foodItem = mock(FoodItem.class);
// Comment indiquer qu'il a plus de 3 vitamines ?
boolean isHealty = fruitService.isHealthy(foodItem);
assertThat(isHealty).isTrue();
}
@nphumbert – @rnowif
public class FruitService {
public boolean isHealthy(FoodItem foodItem) {
Set<Vitamine> vitamines = foodItem.getVitamines();
return vitamines.size() > 3;
}
}
@nphumbert – @rnowif
@Test
public void should_be_healthy_when_more_than_3_vitamines {
FoodItem foodItem = mock(FoodItem.class);
when(foodItem.getVitamines()).thenReturn(newHashSet(A, B, C, D));
boolean isHealty = fruitService.isHealthy(foodItem);
assertThat(isHealty).isTrue();
}
@nphumbert – @rnowif
Injecter des mocks
@nphumbert – @rnowif
Réduire le nombre de tests par classe et les garder concis
@nphumbert – @rnowif
public class FruitService {
public boolean isHealthy(FoodItem foodItem) {
return foodItem.getVitamines() > 3;
}
}
@nphumbert – @rnowif
@Test
public void should_be_healthy_when_more_than_3_vitamines {
FoodItem foodItem = new MockFoodItem(newHashSet(A, B, C, D));
boolean isHealty = fruitService.isHealthy(foodItem);
assertThat(isHealty).isTrue();
}
@nphumbert – @rnowif
public interface FoodItem {
Set<Vitamine> getVitamines();
Color getColor();
Flavor getFlavor();
Size getSize();
String getName();
boolean isOrganic();
Collection<Allergen> getAllergens();
boolean isExpired();
// ...
}
@nphumbert – @rnowif
@nphumbert – @rnowif
public class FruitService {
public boolean isHealthy(Nutrient nutrient) {
return nutrient.getVitamines() > 3;
}
}
public interface Nutrient {
Set<Vitamine> getVitamines();
}
@nphumbert – @rnowif
@Test
public void should_be_healthy_when_more_than_3_vitamines {
Nutrient nutrient = () -> newHashSet(A, B, C, D);
boolean isHealty = fruitService.isHealthy(nutrient);
assertThat(isHealty).isTrue();
}
@nphumbert – @rnowif
Pouvoir créer ses propres mocks
@nphumbert – @rnowif
Du code facilement testable
@nphumbert – @rnowif
@nphumbert (nphumbert.github.io)
Crafties @ YouTube
@rnowif (rnowif.github.io)