Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test multiple properties of an object

Tags:

php

phpunit

I'm getting a JSON structure from an API and need to check, whether the successfull response has two specific attributes with specific values.

Key problems:

  1. I cannot compare the whole object, as there are some properties, which may vary with each request
  2. I cannot write two tests (for each attribute), because it can be considered as successful response only when both attributes matches the right values.

Example successful response:

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

Dirty solution would be

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

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

But I think there must be better and cleaner solution, is there?

like image 495
Radek Simko Avatar asked Aug 03 '12 13:08

Radek Simko


People also ask

How can you find the number of properties in an object?

Use the Object. keys() method, passing the object you want to inspect, to get an array of all the (own) enumerable properties of the object.

How many object properties does an object have?

JavaScript objects have two types of properties: data properties and accessor properties.

Which method is used to check the specific property values?

To wait for an object to have a specific property value, you use the WaitProperty method. The parameters of this method specify: Property name. Expected value.


2 Answers

You want to use assertEquals() for each property you want to verify. While you typically want to test only one thing in each test case, sometimes multiple assertions are required in order to test that "one thing". For this reason, multiple assertions are okay.

You may also want to assert that the properties exist on the $response object to avoid notices. See the following for an example:

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);
}
like image 107
JamesArmes Avatar answered Oct 17 '22 14:10

JamesArmes


Compute the difference between the response and the right answer ignoring any excessive values. If there's no difference, everything's fine; if there is, you'll get the complete information.

//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)

Then you may use assertEqual(whatIsWrong(...), array()), which should output the difference on failure, or handle it in pretty much any preferred way.

like image 40
Bugs Avatar answered Oct 17 '22 15:10

Bugs