3

The method down below creates an user within my application and I check the outcome with two if's.

public function register($request, $response)
{
    // code

    if(isset($new_user->body->ok)) {
        if($new_user->body->ok == true) {
            return $response->withStatus(201);
        }
    } 
}

Now I want to unit test this function. I'm quite confused if it is okay to use more than one assert.

This is what I have. Would you use approach a) or b) or a completly different way?

a)

$this->assertTrue(isset($new_user->body->ok);
$this->assertEquals(true, $new_user->body->ok);     

b)

$this->assertTrue(isset($new_user->body->ok) && $new_user->body->ok == true);
4

Neither

Ideally you want a unit test per potential outcome of your code, with exactly one assert.

The pseudo-code would look something like this:

successful_registration_returns_201()
{
    // set up required objects & data - use mocks and stubs for dependencies
    $response -> register($request, $response)

    assertTrue($response.Status == 201)
}

Unless your response variable includes the new user information, that's all you need to assert on a successful outcome.

To assert on an unsuccessful registration attempt, you'd need to set up your request object to fail registration. Then, depending on how granular your failure code is, you could assert one of:

  • response status is not 201 (only use this if you're not differentiating between different failure types)
  • response includes an expected failure message (if you're sending one back, such as "username already exists" - in this case you'd have one unit test per failure message)

No matter how your code is structured, your unit tests should only assert on the output of the unit, not on variable assignations within the unit.

0

Optimize asserts for readability, your suggestion to group assert into a single one does to opposite if you ask me.

The obvious benefits from having only one assert are greatly overrated. As Long you test the same behaviour I would be fine with multiple asserts in a single test, as are old-timers like James Shore.

Your code example:

return $response->withStatus(201);

I would think the response is the behavior you want to test, not the implementation that you are now testing. Your tests have the same code as the implementation, this is a clear smell. Read this blog Test Behaviour, Not Implementation.

Use common sense, duplicating test-code just to keep it within a single assert seems a waste.

  • Thank you for pointing out the difference to me between testing the behaviour and testing the implementation. This wasn't quite clear for me because I'm just beginning to learn the art of unit testing. I'll take a look into your two links. Cheers! – Magiranu Nov 20 '17 at 19:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.