2012-08-03 19 views
7

Obtengo una estructura JSON de una API y necesito verificar si la respuesta exitosa tiene dos atributos específicos con valores específicos.Cómo probar varias propiedades de un objeto

problemas clave:

  1. que no puedo comparar la totalidad del objeto, ya que hay algunas propiedades, que pueden variar con cada solicitud
  2. no puedo escribir dos pruebas (para cada atributo), ya que puede ser se considera una respuesta exitosa solo cuando ambos atributos coinciden con los valores correctos.

Ejemplo respuesta exitosa:

{ 
    'success': true, 
    'user_ip': '212.20.30.40', 
    'id': '7629428643' 
} 

solución sucia sería

<?php 
public function testAddAccount() { 
    $response = $this->api->addAccount('7629428643'); 

    $this->assertTrue(
     $response->success === TRUE && 
     $response->id === '7629428643' 
    ); 
} 

Pero creo que debe ser mejor y más limpia solución, ¿verdad?

+2

Eso se ve bastante limpio para mí. – Matt

+0

Esa solución solo puede decirle que la prueba falla, pero no le puede decir qué es exactamente lo que falla, por eso la considero "sucia". –

Respuesta

0

Si assertTrue() almacena el booleano de una respuesta exitosa esta es la forma en que lo manejaría. Tenga en cuenta que esto es una cuestión de gusto.

private $lastResponse; 
// $id given elsewhere 
public function testAddAccount($id) { 
    $this->lastResponse = $this->addAccount($id); 
} 

private function addAccount($id) { 
    return $this->api->addAccount($id); 
} 

private function isLastResponseValid($response){ 
    return $this->lastResponse->success === TRUE 
    && $this->lastResponse->id === '7629428643'; 
} 
0

Puede usar múltiples aserciones en un solo método de prueba para casos como este. Además, use las aserciones más específicas como assertEquals siempre que sea posible, ya que proporcionarán mejores mensajes de falla.

public function testAddAccount() { 
    $response = $this->api->addAccount('7629428643'); 

    self::assertTrue($response->success); 
    self::assertEquals('7629428643', $response->id); 
} 
0

Como se mencionó en alguna respuesta, se debe utilizar assertEquals() método. La segunda parte es que puedes usar algunas afirmaciones. Entonces, si phpunit detecta falla en la primera aserción, la prueba falla.

¿Por qué no usar assertTrue()? Porque no está claro si, por ejemplo, usa if ($object) ... en un lugar de código y assertTrue($object); en otro.

Además, asegúrese de que su rutina se ejecuta correctamente. Entonces, si obtiene la excepción al intentar obtener la respuesta, la prueba fallará. Si bien las excepciones deben verificarse también como casos de prueba. Es decir, debe intentar publicar una solicitud incorrecta y lanzar una excepción. Eso es lo bueno de prueba se parece - que debe comprobar todas las situaciones posibles, jeje =)

Por lo tanto, este es el código que debe conseguido:

public function testAddAccount() { 
    $response = $this->api->addAccount('7629428643'); 

    $this->assertEquals($response->success, true); 
    $this->assertEquals($response->id, '7629428643'); 

    $this->setExpectedException('MyException'); 

    $response = $this->api->addAccount('wrong_account'); 
} 
2

Desea utilizar assertEquals() para cada propiedad que desea verificar . Si bien normalmente desea probar solo una cosa en cada caso de prueba, a veces se requieren varias afirmaciones para probar esa "única cosa". Por esta razón, múltiples aserciones están bien.

Es posible que también desee afirmar que las propiedades existen en el objeto $response para evitar avisos.Vea lo siguiente para un ejemplo:

public function testAddAccount() { 
    // Attempt to create an account. 
    $response = $this->api->addAccount('7629428643'); 

    // Verify that the expected properties are present in the response. 
    $this->assertObjectHasAttribute('success', $response); 
    $this->assertObjectHasAttribute('id', $response); 

    // Verify the values of the properties. 
    $this->assertEquals(true, $response->success); 
    $this->assertEquals('7629428643', $response->id); 
} 
+0

Aún así, tiene un defecto en el camino, que en caso de falla, muestra que solo fallaste en la primera afirmación problemática, una vez que la corriges, te muestra otra. –

+0

Esto es cierto, pero de todos modos es mejor enfocarse en una falla a la vez. No es raro que corregir la primera falla también resuelva las fallas restantes dentro de un caso de prueba. – JamesArmes

0

La manera más limpia que puedo pensar (aunque esto es una cuestión de gusto) sería añadir las dos expresiones booleanas y hacer valer el resultado es dos:

$r1=$response->success === TRUE; 
$r2=$response->id === '7629428643'; 
$this->assertEquals(2, $r1+$r2, "Expecting both values to match; got ($r1) and ($r2)"); 

Por supuesto, puede extender esta configuración a cualquier número de pruebas con matrices y array_sum()==count(), y más mensajes adorables.

1

Calcule la diferencia entre la respuesta y la respuesta correcta ignorando los valores excesivos. Si no hay diferencia, todo está bien; si lo hay, obtendrás la información completa.

//some examples 
$responseValues = array('success' => true, 'user_ip' => '212.20.30.40', 'id' => '7629428643'); //success 
$errorResponseValues = array('success' => false, 'user_ip' => '212.20.30.40', 'id' => '7629428643'); //failure 
$errorResponseValues2 = array('success' => false, 'user_ip' => '212.20.30.40', 'id' => '123'); //failure 

$expectedValues = array('success' => true, 'id' => '7629428643'); //what is success 

function whatIsWrong($reality, $expectation) 
{ 
    return array_uintersect_assoc($reality, $expectation, function($a, $b){return (int)($a == $b);}); //This is slightly dirty, I think the final implementation is up to you 
} 

var_dump(whatIsWrong($responseValues, $expectedValues)); //array() 
var_dump(whatIsWrong($errorResponseValues, $expectedValues)); //array('success' => false) 
var_dump(whatIsWrong($errorResponseValues2, $expectedValues)); //array('success' => false, id => 123) 

entonces puede usar assertEqual (whatIsWrong (...), array()), que debe emitir la diferencia en caso de fallo, o manejarlo de casi cualquier manera preferida.

Cuestiones relacionadas