I. Introduction▲
Nos programmes utilisent de nombreux POJO : Plain Old Java Objects. Ces beans très simples sont généralement constitués d'attributs privés, parfois marqués « final », qu'on manipule via des getters et des setters. Pour des raisons pratiques, certains sont équipés de constructeurs reprenant lesdits attributs, en plus du constructeur par défaut. Et pour compléter le tout, on leur ajoute souvent les méthodes equals, hashCode et toString, héritées de Object.
La plupart des IDE (Eclipse, Idea, etc.) permettent d'ajouter toutes ces méthodes (getters, setters, constructeurs, equals, hashCode et toString) aux beans en quelques clics, si bien que la plupart des développeurs considèrent les POJO comme des beans de second plan. On les croit fiables. On n'y prête pas attention. On les ignore même dans les tests. C'est bien entendu une erreur, car de nombreux problèmes peuvent en résulter, mais qui lancera la première pierre ?
La bibliothèque Pojo-Tester, sous licence GNU GPL 3, s'intéresse spécifiquement à ces beans. Elle offre des mécanismes simples et efficaces pour les tester de fond en comble.
Pourquoi allez-vous donc utiliser Pojo-Tester ? À quoi cette bibliothèque va-t-elle vous servir ? D'abord à augmenter le score de votre couverture de code, même si c'est superficiel. Ensuite, et surtout, à sécuriser les méthodes de vos beans qui serait quasiment intestables sans. Pensez, par exemple, aux mauvais copiés-collés dans vos getters/setters ou dans l'enchaînement d'égalité de la méthode equals. Considérez aussi l'ajout d'un attribut, après coup, qui aurait été pris en compte dans equals, mais oublié dans hashCode. C'est une véritable galère d'identifier ce genre de bogue…
II. Projet d'exemple▲
Voici quelques éléments vraiment triviaux qui vont nous permettre d'illustrer le fonctionnement de la bibliothèque Pojo-Tester à moindre coût. Les codes complets sont proposés en annexes. Le projet dvp-article-pojo-tester est également disponible sur GitHub.
II-A. Bean et service▲
Pour commencer, disons que nous avons un bean Chien contenant quelques attributs (cf. ci-dessous). Pour faire bonne mesure, on demande à Eclipse de générer les méthodes hashCode, equals et toString, ainsi que les getters et les setters :
public
class
Chien {
private
String name;
private
String race;
private
double
poids; // Poids en kg
private
double
taille; // Taille exprimee en metre
private
Date dateNaissance;
private
List<
String>
couleurs;
public
Chien
(
) {
}
// + Getters / Setters
// + hashCode / equals
// + toString
...
Juste pour l'exemple, disons qu'on écrit ChienService, une classe proposant un ensemble de fonctionnalités liées aux chiens.
public
class
ChienService {
public
int
calculerIMC
(
final
Chien chien) {
return
(
int
) (
chien.getPoids
(
) /
Math.pow
(
chien.getTaille
(
), 2
));
}
...
II-B. Maven▲
Dans notre projet Maven, on indique une dépendance vers JUnit puisqu'on va écrire des tests.
<project ...>
...
<properties>
<maven.compiler.source>
1.8</maven.compiler.source>
<maven.compiler.target>
1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>
junit</groupId>
<artifactId>
junit</artifactId>
<version>
4.12</version>
</dependency>
</dependencies>
On ajoute aussi une dépendance vers Jacoco, une bibliothèque (similaire à Cobertura) permettant de mesurer la couverture de code de notre programme.
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>
org.jacoco</groupId>
<artifactId>
jacoco-maven-plugin</artifactId>
<version>
0.7.9</version>
<executions>
<execution>
<id>
default-prepare-agent</id>
<goals>
<goal>
prepare-agent</goal>
</goals>
</execution>
<execution>
<id>
default-report</id>
<phase>
prepare-package</phase>
<goals>
<goal>
report</goal>
</goals>
</execution>
<execution>
<id>
default-check</id>
<goals>
<goal>
check</goal>
</goals>
<configuration>
<rules>
<rule
implementation
=
"org.jacoco.maven.RuleConfiguration"
>
<element>
BUNDLE</element>
<limits>
<limit
implementation
=
"org.jacoco.report.check.Limit"
>
<counter>
COMPLEXITY</counter>
<value>
COVEREDRATIO</value>
<minimum>
0.70</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Cette configuration indique qu'on attend une couverture d'au moins 70 %, faute de quoi le build Maven se terminera en erreur.
II-C. Tests évidents▲
Pour tester convenablement l'objet Chien, il ne faudrait pas moins de huit tests. Pour l'instant on va donc seulement se concentrer sur le service. Voici le genre de test qu'on pourrait écrire :
public
class
ChienServiceTest {
private
ChienService chienService =
new
ChienService
(
);
@Test
public
void
testCalculerIMCMilou
(
) {
// Arrange
final
double
taille =
0.39
;
final
double
poids =
9
;
final
int
expectedIMC =
59
;
// Arrange obj
final
Chien milou =
new
Chien
(
);
milou.setTaille
(
taille);
milou.setPoids
(
poids);
// Act
final
int
imc =
chienService.calculerIMC
(
milou);
// Assert
Assert.assertEquals
(
expectedIMC, imc);
}
C'est le formalisme AAA (Arrange, Act and Assert), si cher à votre serviteur, qui est utilisé ici.
Voici, ci-dessous, les rapports de Jacoco à propos de la couverture du code à ce stade :
III. Action▲
On va maintenant s'occuper des POJO de notre programme.
III-A. Ajouter Pojo-Tester▲
Pour commencer, on ajoute la dépendance à Pojo-Tester :
<project ...>
...
<dependencies>
...
<dependency>
<groupId>
pl.pojo</groupId>
<artifactId>
pojo-tester</artifactId>
<version>
0.7.5</version>
</dependency>
</dependencies>
On aura également besoin de préciser le repository où trouver la bibliothèque Pojo-Tester :
<project ...>
...
<repositories>
<repository>
<id>
jcenter</id>
<url>
http://jcenter.bintray.com/</url>
</repository>
</repositories>
III-B. Bean classique : Chien▲
Le bean Chien, qui représente sans aucun doute le cas le plus classique, est facile à tester :
import
static
pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsFor;
public
class
AnimalTest {
@Test
public
void
testPojoChien
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chien.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.areWellImplemented
(
);
}
Voici, ci-dessous, ce que ça donne au niveau de la couverture du code avec Jacoco. On constate que toutes les méthodes ont bien été couvertes (avec un petit raté sur equals). Magique, facile ?
À cette date, la bibliothèque a encore du mal a bien tester ma méthode equals. Il reste des instructions non couvertes. Espérons que les futures versions fassent évoluer le sujet.
Ajoutons maintenant le nouvel attribut « méchant » au bean Chien et demandons à Eclipse d'en générer le getter et le setter. Ici on va faire exprès d'oublier de faire évoluer equals, hashCode et toString.
public
class
Chien {
...
private
boolean
mechant; // juste getter/setter
...
public
boolean
isMechant
(
) {
return
mechant;
}
public
void
setMechant
(
boolean
mechant) {
this
.mechant =
mechant;
}
Là, Pojo-Tester va nous rappeler à l'ordre ; un oubli est vite arrivé et peut passer longtemps inaperçu. Charge ensuite au développeur de choisir quoi faire en piochant dans les techniques abordées dans les prochains chapitres.
Class com.dvp.tld.article.pojotester.domaine.Chien has bad 'toString'
method implementation.
The toString method should contain:
mechant
=
false
But does not.
Result of toString:
Chien [name
=
null, race
=
null, poids
=
0
.0
, taille
=
0
.0
, dateNaissance
=
null, couleurs
=
null]
III-C. Bean immutable : Lapin▲
Ajoutons maintenant le bean Lapin ayant la particularité de posséder des attributs marqués « final ». Ça change quelque peu la donne.
public
class
Lapin {
// Attributs final
private
final
String name;
private
final
int
age;
// + Getters
// + hashCode / equals
// + toString
...
Le bean Lapin n'a pas de setter puisque tous ses attributs sont « final ».
Essayons d'appliquer la même stratégie que pour le bean Chien :
public
class
AnimalTest {
@Test
public
void
testPojoLapinFailed
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Lapin.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.areWellImplemented
(
);
}
Le test échoue naturellement puisque Pojo-Tester ne trouve pas de setter :
Tests in
error:
testPojoLapinFailed
(
...AnimalTest): Class ...Lapin has no setter for
field private final ...String ...Lapin.name
Les noms de classes et d'attributs ont été tronqués dans le message d'erreur ci-dessus pour en faciliter la lecture.
Il faut donc préciser les méthodes qu'on souhaite tester :
import
static
pl.pojo.tester.api.assertion.Method.CONSTRUCTOR;
import
static
pl.pojo.tester.api.assertion.Method.EQUALS;
import
static
pl.pojo.tester.api.assertion.Method.GETTER;
import
static
pl.pojo.tester.api.assertion.Method.HASH_CODE;
import
static
pl.pojo.tester.api.assertion.Method.SETTER;
import
static
pl.pojo.tester.api.assertion.Method.TO_STRING;
public
class
AnimalTest {
@Test
public
void
testPojoLapin
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Lapin.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.testing
(
TO_STRING) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
}
Ici, EQUALS et HASH_CODE sont sur la même ligne (dans la même instruction) pour insister sur le fait que les deux méthodes associées fonctionnent en paire. Elles doivent respecter le même contrat. Par extension, cela doit se traduire aussi dans les tests.
Et là ça fonctionne, comme on peut le voir sur le rapport de Jacoco :
III-D. Bean semi-immutable : Chat▲
On va compliquer encore les choses avec le bean Chat dans lequel seuls les attributs « name » et « age » sont pris en compte pour le constructeur et les méthodes hashCode et equals :
public
class
Chat {
// Attributs principaux (dans cons, hashcode et equals)
private
final
String name;
private
final
int
age;
// Attributs en plus
private
double
poids;
private
String moustache;
private
String[] petits;
public
Chat
(
String name, int
age) {
super
(
);
this
.name =
name;
this
.age =
age;
}
// + Getters / Setters
// + hashCode / equals
// + toString
...
Si on tente de tester Chat comme on l'avait fait avec Lapin, ça ne va évidemment pas être bon :
public
class
AnimalTest {
@Test
public
void
testPojoChatFailed
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chat.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.testing
(
TO_STRING) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
}
Le build Maven va en effet nous donner l'erreur suivante, indiquant que la méthode hashCode n'est pas correcte. Notez que le test s'arrête à la première erreur sans rien dire des éventuelles autres erreurs :
Class ...Chat has bad 'hashCode'
method implementation.
The hashCode method should return
different hash codes for
non equal objects.
Current implementation returns same hash codes.
Object:
Chat [name
=
www.pojo.pl, age
=
-4
, poids
=
0
.0
, moustache
=
null, petits
=
null]
and
Chat [name
=
www.pojo.pl, age
=
-4
, poids
=
-2
.5
, moustache
=
null, petits
=
null]
should have different hash codes:
1122311828
and
1122311828
Il faut donc préciser les attributs qu'on souhaite prendre en compte pour chaque méthode, ce qui donne lieu à plusieurs appels dans le test. Ici on parlera d'inclusion :
import
static
pl.pojo.tester.api.FieldPredicate.include;
public
class
AnimalTest {
@Test
public
void
testPojoChatInclude
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chat.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest, include
(
"name"
, "age"
)) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest, include
(
"poids"
, "moustache"
, "petits"
)) //
.testing
(
SETTER) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.testing
(
TO_STRING) //
.areWellImplemented
(
);
}
Ce n'est pas très pratique de fonctionner par inclusion. La bibliothèque permet aussi de travailler par exclusion :
import
static
pl.pojo.tester.api.FieldPredicate.include;
public
class
AnimalTest {
@Test
public
void
testPojoChatExclude
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chat.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest, exclude
(
"poids"
, "moustache"
, "petits"
)) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest, exclude
(
"name"
, "age"
)) //
.testing
(
SETTER) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.areWellImplemented
(
);
}
Bien entendu, rien n'empêche de travailler à fois par inclusion et par exclusion, si cela vous semble plus simple.
Les auteurs de Pojo-Tester conseillent de privilégier les exclusions. Pourquoi ça ? Disons qu'on ajoute un attribut au bean mais qu'on oublie d'en tenir compte dans la méthode equals. Dans ce cas, la bibliothèque va s'en rendre compte si on travaille par exclusion. Au contraire, si on a oublié l'attribut dans equals, il est plus que probable qu'on l'aura aussi oublié dans inclusions, CQFD…
III-E. Dauphin Lombok : Dauphin▲
Si, comme votre serviteur, vous aimez la bibliothèque Lombok, vous serez content d'apprendre que Pojo-Tester saura gérer. Mais ajoutons d'abord Lombok à la liste de nos dépendances :
<project ...>
...
<dependencies>
...
<dependency>
<groupId>
org.projectlombok</groupId>
<artifactId>
lombok</artifactId>
<version>
1.16.16</version>
</dependency>
</dependencies>
Une introduction à Lombok est proposée dans un article intitulé « Simplifier le code de vos beans Java à l'aide de Commons Lang, Guava et Lombok ».
Ici on va simplement annoter le bean Dauphin avec @Data, qui génère toute la série des méthodes qu'on a déjà utilisées dans le reste de cet article.
import
lombok.Data;
@Data
public
class
Dauphin {
private
String name;
private
int
speed;
Au niveau du test de Dauphin, on se contente de recopier le test classique qu'on avait écrit pour Chien :
import
static
pl.pojo.tester.api.FieldPredicate.include;
public
class
AnimalTest {
@Test
public
void
testPojoDauphin
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Dauphin.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.areWellImplemented
(
);
}
Et ça marche du premier coup, comme l'atteste le rapport Jacoco.
IV. Conclusion▲
Une fois n'est pas coutume, le contrat d'un article en cinq minutes est presque rempli. Il faut dire que le sujet semblait simple, du moins en apparence. Il est toutefois bien plus riche qu'on ne le pense au premier contact. La bibliothèque Pojo-Tester est ce genre d'outil qu'on ajoute à sa collection pour un besoin ponctuel et qui devient rapidement un incontournable, voire un irremplaçable.
Pojo-Tester se présente clairement comme un outil de test, mais la plupart des développeurs, y compris votre serviteur, vont initialement l'utiliser pour augmenter leur score de couverture. Il faut avouer qu'un score élevé fait toujours plaisir. Pour en obtenir un, de nombreux projets vont d'ailleurs tout simplement ignorer les POJO, qu'on considère généralement comme dénués de risque et/ou d'une importance secondaire. Même si c'est vrai au lancement du projet, cela devient une erreur avec le temps. En effet, qui n'a jamais été confronté à un bogue issu d'un mauvais copié-collé dans un getter/setter ou un attribut ajouté après coup au bean, mais oublié dans le equals/hashCode ? Ce genre de bogue est facile à corriger, mais hyperdifficile à identifier, ce qui fait perdre beaucoup de temps. La bibliothèque Pojo-Tester permet de s'en prémunir.
Pojo-Tester souffre néanmoins de quelques manques. On a déjà parlé de la méthode equals pour laquelle la couverture n'est pas complète. Gageons que cela sera amélioré avec le temps. Même ainsi, c'est une bibliothèque qu'on ne pourrait que conseiller d'avoir dans votre boîte à outils.
Vos retours et remarques nous aident à améliorer les publications de Developpez.com. N'hésitez donc pas à commenter cet article. Commentez
V. Remerciements▲
J'adresse mes remerciements aux auteurs de la bibliothèque Pojo-Tester. Merci de l'avoir créé et de la maintenir. Elles aident de nombreux développeurs à travers le monde.
Merci également à tous ceux qui ont contribué à la rédaction de cet article : Mickael Baron, jacques_jean et Winjerome.
VI. Annexes▲
VI-A. Liens▲
Projet dvp-article-pojo-tester sur GitHub : https://github.com/thierryler/dvp-article-pojo-tester
Pojo-Tester : http://www.pojo.pl/
Jacoco : http://www.eclemma.org/jacoco/
Lombok : https://projectlombok.org/
Mes autres articles : http://thierry-leriche-dessirier.developpez.com/
VI-B. Codes entiers▲
package
com.dvp.tld.article.pojotester.domaine;
import
java.util.Date;
import
java.util.List;
public
class
Chien {
private
String name;
private
String race;
private
double
poids; // Poids en kg
private
double
taille; // Taille exprimee en metre
private
Date dateNaissance;
private
List<
String>
couleurs;
// private boolean mechant; // juste getter/setter
public
Chien
(
) {
// Rien
}
@Override
public
String toString
(
) {
return
"Chien [name="
+
name +
", race="
+
race +
", poids="
+
poids +
", taille="
+
taille +
", dateNaissance="
+
dateNaissance +
", couleurs="
+
couleurs +
"]"
;
}
@Override
public
int
hashCode
(
) {
final
int
prime =
31
;
int
result =
1
;
result =
prime *
result +
((
couleurs ==
null
) ? 0
: couleurs.hashCode
(
));
result =
prime *
result +
((
dateNaissance ==
null
) ? 0
: dateNaissance.hashCode
(
));
result =
prime *
result +
((
name ==
null
) ? 0
: name.hashCode
(
));
long
temp;
temp =
Double.doubleToLongBits
(
poids);
result =
prime *
result +
(
int
) (
temp ^
(
temp >>>
32
));
result =
prime *
result +
((
race ==
null
) ? 0
: race.hashCode
(
));
temp =
Double.doubleToLongBits
(
taille);
result =
prime *
result +
(
int
) (
temp ^
(
temp >>>
32
));
return
result;
}
@Override
public
boolean
equals
(
Object obj) {
if
(
this
==
obj)
return
true
;
if
(
obj ==
null
)
return
false
;
if
(
getClass
(
) !=
obj.getClass
(
))
return
false
;
Chien other =
(
Chien) obj;
if
(
couleurs ==
null
) {
if
(
other.couleurs !=
null
)
return
false
;
}
else
if
(!
couleurs.equals
(
other.couleurs))
return
false
;
if
(
dateNaissance ==
null
) {
if
(
other.dateNaissance !=
null
)
return
false
;
}
else
if
(!
dateNaissance.equals
(
other.dateNaissance))
return
false
;
if
(
name ==
null
) {
if
(
other.name !=
null
)
return
false
;
}
else
if
(!
name.equals
(
other.name))
return
false
;
if
(
Double.doubleToLongBits
(
poids) !=
Double.doubleToLongBits
(
other.poids))
return
false
;
if
(
race ==
null
) {
if
(
other.race !=
null
)
return
false
;
}
else
if
(!
race.equals
(
other.race))
return
false
;
if
(
Double.doubleToLongBits
(
taille) !=
Double.doubleToLongBits
(
other.taille))
return
false
;
return
true
;
}
public
String getName
(
) {
return
name;
}
public
void
setName
(
String name) {
this
.name =
name;
}
public
String getRace
(
) {
return
race;
}
public
void
setRace
(
String race) {
this
.race =
race;
}
public
double
getPoids
(
) {
return
poids;
}
public
void
setPoids
(
double
poids) {
this
.poids =
poids;
}
public
double
getTaille
(
) {
return
taille;
}
public
void
setTaille
(
double
taille) {
this
.taille =
taille;
}
public
Date getDateNaissance
(
) {
return
dateNaissance;
}
public
void
setDateNaissance
(
Date dateNaissance) {
this
.dateNaissance =
dateNaissance;
}
public
List<
String>
getCouleurs
(
) {
return
couleurs;
}
public
void
setCouleurs
(
List<
String>
couleurs) {
this
.couleurs =
couleurs;
}
// public boolean isMechant() {
// return mechant;
// }
//
// public void setMechant(boolean mechant) {
// this.mechant = mechant;
// }
}
package
com.dvp.tld.article.pojotester.domaine;
public
class
Lapin {
// Attributs final
private
final
String name;
private
final
int
age;
public
Lapin
(
final
String name, final
int
age) {
this
.name =
name;
this
.age =
age;
}
@Override
public
int
hashCode
(
) {
final
int
prime =
31
;
int
result =
1
;
result =
prime *
result +
age;
result =
prime *
result +
((
name ==
null
) ? 0
: name.hashCode
(
));
return
result;
}
@Override
public
boolean
equals
(
Object obj) {
if
(
this
==
obj)
return
true
;
if
(
obj ==
null
)
return
false
;
if
(
getClass
(
) !=
obj.getClass
(
))
return
false
;
Lapin other =
(
Lapin) obj;
if
(
age !=
other.age)
return
false
;
if
(
name ==
null
) {
if
(
other.name !=
null
)
return
false
;
}
else
if
(!
name.equals
(
other.name))
return
false
;
return
true
;
}
@Override
public
String toString
(
) {
return
"Lapin [name="
+
name +
", age="
+
age +
"]"
;
}
public
String getName
(
) {
return
name;
}
public
int
getAge
(
) {
return
age;
}
}
package
com.dvp.tld.article.pojotester.domaine;
import
java.util.Arrays;
public
class
Chat {
// Attributs principaux (dans cons, hashcode et equals)
private
final
String name;
private
final
int
age;
// Attributs en plus
private
double
poids;
private
String moustache;
private
String[] petits;
public
Chat
(
String name, int
age) {
super
(
);
this
.name =
name;
this
.age =
age;
}
public
String getName
(
) {
return
name;
}
public
int
getAge
(
) {
return
age;
}
@Override
public
String toString
(
) {
return
"Chat [name="
+
name +
", age="
+
age +
", poids="
+
poids +
", moustache="
+
moustache +
", petits="
+
Arrays.toString
(
petits) +
"]"
;
}
@Override
public
int
hashCode
(
) {
final
int
prime =
31
;
int
result =
1
;
result =
prime *
result +
age;
result =
prime *
result +
((
name ==
null
) ? 0
: name.hashCode
(
));
return
result;
}
@Override
public
boolean
equals
(
Object obj) {
if
(
this
==
obj)
return
true
;
if
(
obj ==
null
)
return
false
;
if
(
getClass
(
) !=
obj.getClass
(
))
return
false
;
Chat other =
(
Chat) obj;
if
(
age !=
other.age)
return
false
;
if
(
name ==
null
) {
if
(
other.name !=
null
)
return
false
;
}
else
if
(!
name.equals
(
other.name))
return
false
;
return
true
;
}
public
double
getPoids
(
) {
return
poids;
}
public
void
setPoids
(
double
poids) {
this
.poids =
poids;
}
public
String getMoustache
(
) {
return
moustache;
}
public
void
setMoustache
(
String moustache) {
this
.moustache =
moustache;
}
public
String[] getPetits
(
) {
return
petits;
}
public
void
setPetits
(
String[] petits) {
this
.petits =
petits;
}
}
package
com.dvp.tld.article.pojotester.domaine;
import
lombok.Data;
@Data
public
class
Dauphin {
private
String name;
private
int
speed;
}
package
com.dvp.tld.article.pojotester.domaine;
import
static
pl.pojo.tester.api.FieldPredicate.exclude;
import
static
pl.pojo.tester.api.FieldPredicate.include;
import
static
pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsFor;
import
static
pl.pojo.tester.api.assertion.Method.CONSTRUCTOR;
import
static
pl.pojo.tester.api.assertion.Method.EQUALS;
import
static
pl.pojo.tester.api.assertion.Method.GETTER;
import
static
pl.pojo.tester.api.assertion.Method.HASH_CODE;
import
static
pl.pojo.tester.api.assertion.Method.SETTER;
import
static
pl.pojo.tester.api.assertion.Method.TO_STRING;
import
org.junit.Ignore;
import
org.junit.Test;
public
class
AnimalTest {
@Test
public
void
testPojoChien
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chien.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.areWellImplemented
(
);
}
@Ignore
@Test
public
void
testPojoLapinFailed
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Lapin.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.areWellImplemented
(
);
}
@Test
public
void
testPojoLapin
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Lapin.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.testing
(
TO_STRING) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
}
@Test
@Ignore
public
void
testPojoChatFailed
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chat.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.testing
(
TO_STRING) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
}
@Test
public
void
testPojoChatInclude
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chat.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest, include
(
"name"
, "age"
)) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest, include
(
"poids"
, "moustache"
, "petits"
)) //
.testing
(
SETTER) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.testing
(
TO_STRING) //
.areWellImplemented
(
);
}
@Test
public
void
testPojoChatExclude
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Chat.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest, exclude
(
"poids"
, "moustache"
, "petits"
)) //
.testing
(
EQUALS, HASH_CODE) //
.testing
(
CONSTRUCTOR) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest, exclude
(
"name"
, "age"
)) //
.testing
(
SETTER) //
.areWellImplemented
(
);
assertPojoMethodsFor
(
classUnderTest) //
.testing
(
GETTER) //
.areWellImplemented
(
);
}
@Test
public
void
testPojoDauphin
(
) {
// Arrange
final
Class<
?>
classUnderTest =
Dauphin.class
;
// Act
// Assert
assertPojoMethodsFor
(
classUnderTest) //
.areWellImplemented
(
);
}
}