2012-08-28 13 views
70

asume que desea probar unidad de un método con esta firma:¿Cómo afirmo que un Iterable contiene elementos con una cierta propiedad?

List<MyItem> getMyItems(); 

Supongamos MyItem es un Pojo que tiene muchas propiedades, una de las cuales es "name", accede a través de getName().

Todo lo que importa es que la verificación de la List<MyItem>, o cualquier Iterable, contiene dos instancias MyItem, cuya "name" propiedades tener los valores "foo" y "bar". Si otras propiedades no coinciden, realmente no me importan los propósitos de esta prueba. Si los nombres coinciden, es una prueba exitosa.

Me gustaría que fuera de una sola línea si es posible. Aquí hay alguna "pseudo-sintaxis" del tipo de cosas que me gustaría hacer.

assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"}); 

Would Hamcrest ser bueno para este tipo de cosas? Si es así, ¿cuál sería exactamente la versión de Hamcrest de mi pseudo-sintaxis anterior?

Respuesta

76

Gracias @Razvan que me indicó la dirección correcta. Pude conseguirlo en una línea y cacé con éxito las importaciones de Hamcrest 1.3.

las importaciones:

import static org.hamcrest.CoreMatchers.is; 
import static org.hamcrest.Matchers.contains; 
import static org.hamcrest.MatcherAssert.assertThat; 
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; 

el código:

assertThat(myClass.getMyItems(), contains(
    hasProperty("name", is("foo")), 
    hasProperty("name", is("bar")) 
)); 
38

Probar:

assertThat(myClass.getMyItems(), 
          hasItem(hasProperty("YourProperty", is("YourValue")))); 
+1

solo como un nodo lateral - esta es una solución de hamcrest (no assertj) – Hartmut

3

Mientras que su lista es una clase concreta, sólo tiene que llamar al método contains() siempre y cuando se han puesto en práctica sus iguales() en myItem.

// given 
// some input ... you to complete 

// when 
List<MyItems> results = service.getMyItems(); 

// then 
assertTrue(results.contains(new MyItem("foo"))); 
assertTrue(results.contains(new MyItem("bar"))); 

Supone que ha implementado un constructor que acepta los valores que desea establecer. Me doy cuenta de que esto no está en una sola línea, pero es útil saber qué valor falta en lugar de verificar ambos a la vez.

+0

Me gusta mucho su solución, pero ¿debería modificar todo ese código para una prueba? –

+0

Me imagino que cada respuesta aquí requerirá alguna configuración de prueba, la ejecución del método para probar, y luego afirmar las propiedades. No hay una sobrecarga real en mi respuesta por lo que puedo ver, solo que tengo dos afirmaciones en líneas de puente marino para que una afirmación fallida pueda identificar claramente qué valor falta. – Brad

+0

Sería mejor incluir también un mensaje dentro de assertTrue para que el mensaje de error sea más inteligible. Sin un mensaje, si falla, JUnit lanzará un AssertionFailedError sin ningún mensaje de error. Lo mejor es incluir algo así como "los resultados deben contener un nuevo MyItem (\" foo \ ")". – Max

21

No es especialmente Hamcrest, pero creo que vale la pena mencionar aquí. Lo que yo uso bastante a menudo en Java8 es algo así como:

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName()))); 

(... Editado con ligera mejoría de Rodrigo Manyari Es un poco menos detallado ver comentarios)

Puede ser un poco más difícil de leer, pero me gusta el tipo y la seguridad de refactorización. También es bueno para probar múltiples propiedades de frijoles en combinación. p.ej. con una expresión similar a java & & en el filtro lambda.

+2

Ligera mejora: assertTrue (myClass.getMyItems(). Stream(). AnyMatch (item -> "foo" .equals (item.getName ())); –

+0

@RodrigoManyari, falta paréntesis de cierre – Abdull

15

Assertj es bueno en esto.

import static org.assertj.core.api.Assertions.assertThat; 

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar"); 

Big plus para assertj comparado con hamcrest es fácil de usar al completar el código.

Cuestiones relacionadas