1

I'm trying to finalize a unit test but it's failing when I get something from the session and then cast it into an array.

What I'm doing:

public function formatAddress($address) {
        if(empty($address)) {
            $full_address = craft()->httpSession->get('address');
            $full_address = (array) $full_address;
            return $formatted_address = array(
                "address1" => $full_address['street'],
                "city" => $full_address['city'],
                "state" => $full_address['state'],
            );
        } else {
            return $address;
        }
    }



$formatted_address = $this->formatAddress($user['address']);

How it's coming back from the session:

stdClass Object
(
    [city] => Warsaw
    [county] => Hancock
    [id] => 110458115f8a45849a31df1d9144aa62
    [latitude] => 40.27917
    [longitude] => -91.30012
    [state] => IL
    [street] => 1091 E County Road 550
    [zip] => 62379-3212
)

So I take this session variable, typecast it to an array then take those array properties and assign them to keys in another array.

However, when running my unit test it's telling me that there's an undefined index "street" on the 'address1" => $full_address['street'], line?

The function works perfect in my dev, but the unit test is not liking it for some reason.

Unit test:

$mocked_address = array(
            "address1" => "109 some street",
            "city" => "some city",
            "state" => "AZ",
            "zip" => "99955"
        );

          $this->httpSession
            ->shouldReceive('get')
            ->with('address')
            ->andReturn($mocked_address);

1 Answer 1

2

Have a closer look at your $mocked_address object in your test case. You're trying to access the key street that does not exist in that array. This causes a PHP notice. I assume that your development environment is configured to hide such notices via PHP's error_reporting setting. However, PHPUnit is a lot more strict and does not like PHP errors (even tiny ones, like notices) at all.

You have two options:

  1. Just fix your error. If it is possible that an address does not contain a street, check if it is set before accessing it:

    return $formatted_address = array(
        "address1" => isset($full_address['street']) ? $full_address['street'] : NULL,
        "city" => $full_address['city'],
        "state" => $full_address['state'],
    );
    
  2. Configure PHPUnit to not convert PHP notices into exceptions. This can be done by creating a XML configuration file for PHPUnit and setting the convertNoticesToExceptions attribute to false:

    <phpunit
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd"
        convertNoticesToExceptions="true">
        <!-- ... -->
    </phpunit>
    

As a general recommendation, I suggest to always enable PHP notices in your development environment. I've seen quite a lot of bugs that could have easily been prevented by looking at PHP notices.

Sign up to request clarification or add additional context in comments.

4 Comments

Hmmm, that makes sense. I'm just confused because I'm getting 'address' from the session which will always be set. It should ALWAYS have a street attached to it? It makes sense what you're saying, but I'm confused how 'street' could ever not be set if I explicitly set it in my session every time?
If your session data always contain a street key, that's fine. But your test data in your test case do not. There, you're using the address1 key. Is it possible that you've just mixed up the array keys by mistake?
maybe I'm understanding this andReturn() on my get('address')? Should this be returning the mocked session variable? So I'll assign it the keys for the address object it returns? Do I also have to cast this as an object in my unit test since that's how it actually comes back as and I then cast it to an array in my service? e/ - I guess that makes sense if the andReturn() returns the SESSION object.
Should this be returning the mocked session variable; yes, exactly that. andReturn(...) specifies what your mocked function get will return when called; it does not assert what your function under test formatAddress should return.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.