Ya hemos hablado anteriormente de Hamcrest y sus posibilidades aquí. Ahora daremos un paso más y veremos como hacer nuestros propios Matchers. Es verdad que Hamcrest tiene multitud de métodos pero puede sernos necesario algún método concreto, bien porque sea una cualidad específica de nuestras pruebas o por que dicha comprobación se realice multiples veces.
Es posible hacerlo de varias formas y empezaremos con la más básica: BaseMatcher. Debemos extender la clase para crear nuestra prueba. Para los ejemplos usaremos un objeto 'Car' que tiene un atributo entero 'wheels' y un atributo String 'colour'.
@Test public void equal() { Car car = new Car(3, "white"); assertThat(car, hasEnoughWheels()); } private Matcher<Car> hasEnoughWheels() { return new BaseMatcher<Car>() { public boolean matches(final Object item) { final Car car = (Car) item; return car.getWheels() >= 4; } public void describeTo(final Description description) { description.appendText("A car must have at least 4 wheels"); } public void describeMismatch(final Object item, final Description description) { description.appendValue(((Car) item).getWheels() + " are not enough."); } }; }
Si ejecutamos la prueba, tendremos la siguiente salida obtendremos:
La diferencia entre BaseMatcher y nuestra siguiente clase, TypeSafeMatcher, es que esta última verificará el objeto que le pasamos y lo casteará por nosotros. Pero a cambio deberemos implementar otros métodos (matchesSafely y describeMismatchSafely por matches y describeMismatch).
La salida sería:
Luego hay dos clases más DiagnosingMatcher y TypeSafeDiagnosingMatcher que siguen siendo básicamente lo mismo, pero con la cualidad que puedes crear el objeto description dentro del pripio método 'matches'. De esta forma implementamos un único método y no dos.
Y por último está CustomMatcher y su versión TypeSafe, que estan pensadas principalmente para el uso de clases internas. Es decir crear Matcher no reutilizables.
java.lang.AssertionError: Expected: A car must have at least 4 wheels but: "3 are not enough." at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20) ...
La diferencia entre BaseMatcher y nuestra siguiente clase, TypeSafeMatcher, es que esta última verificará el objeto que le pasamos y lo casteará por nosotros. Pero a cambio deberemos implementar otros métodos (matchesSafely y describeMismatchSafely por matches y describeMismatch).
@Test public void equal() { Car car = new Car(3, "white"); assertThat(car, hasCorrectColour("black")); } private Matcher<Car> hasCorrectColour(final String colour) { return new TypeSafeMatcher<Car>() { protected boolean matchesSafely(final Car car) { return colour.equals(car.getColour()); } public void describeTo(final Description description) { description.appendText("A car should have the colour " + colour); } protected void describeMismatchSafely(final Car item, final Description mismatchDescription) { mismatchDescription.appendText("But was: " + item.getColour()); } }; }
La salida sería:
java.lang.AssertionError: Expected: A car should have the colour black but: But was: white at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20) ...
Luego hay dos clases más DiagnosingMatcher y TypeSafeDiagnosingMatcher que siguen siendo básicamente lo mismo, pero con la cualidad que puedes crear el objeto description dentro del pripio método 'matches'. De esta forma implementamos un único método y no dos.
Y por último está CustomMatcher y su versión TypeSafe, que estan pensadas principalmente para el uso de clases internas. Es decir crear Matcher no reutilizables.
@Test public void equal() { Car car = new Car(3, "white"); Coche coche = new Coche(); Matcher<Integer> aPositiveInt = new CustomMatcher<Integer>("a positive int") { public boolean matches(final Object object) { return object instanceof Integer && !((Integer) object < 0); } }; assertThat(-1, aPositiveInt); }
No hay comentarios:
Publicar un comentario