Cara menggunakan phpunit expectexceptionmessagematches

Welcome to PHPUnit!

PHPUnit is a programmer-oriented testing framework for PHP.
It is an instance of the xUnit architecture for unit testing frameworks.

Take the first steps Let me help you Get the eBook

Copyright © Sebastian Bergmann.

Intro

Let's have a shamefully simple class like this:

<?PHP

namespace App;

class Example
{

    public function handle()
    {
        throw new \Exception('Not Found', 404);
    }
}

Back in the days, there were three options for how to test the exception. From PHPunit 9.0 onwards, only two remain. expectedException annotation was deprecated and removed.

Now we can concentrate on existing solutions.

Try Catch

First one is a try-catch pair. I've seen Adam Wathan used it and advocate for it in his TDD course. Some devs consider this to be a big old fashioned. However, it has one advantage. Inside catch block, you can run additional assertion related to exception or even some other parts of the code, e.g. user wasn't updated.

/** @test*/
function exception_is_thrown()
{
    try {
        $example = new Example();
        $example->handle();
    } catch (\Exception $e) {
        $this->assertSame('Not Found', $e->getMessage());
        $this->assertSame(404, $e->getCode());

        // additional assertion e.g. user wasn't updated
        return;
    }

    $this->fail('Exception was not thrown.');
}

Expectations

This approach is the PHPunit's recommended one. You can use four different methods expectException, expectExceptionMessage, expectExceptionMessageMatches. Be aware that apart from those 4, you can't use any other assertions. If you would add $this->assertTrue(false); it would be ignored at the end of the test.

/** @test */
function exception_is_thrown()
{
    $this->expectException(\Exception::class);
    $this->expectExceptionCode(404);
    $this->expectExceptionMessage('Not Found');
    $this->expectExceptionMessageMatches('/Found/');

    $example = new Example();
    $example->handle();
}

Conclusion

They are both excellent strategies to test PHP exceptions. Personally, I use the second one by default. I would use the first one only if additional assertions are needed.

PHPUnit for VSCode

This extension aims to need zero config and to be highly configurable. If you have php in environment path and phpunit installed with composer or anywhere in your workspace as phpunit*.phar, zero config is needed. It will even fallback to spinning up a self-removing docker container to try and run your tests if it can't find php on your machine.

Cara menggunakan phpunit expectexceptionmessagematches

Features

  • Run tests with one command or hotkey based on open file (*.php or phpunit.xml) and cursor position
    • "quick pick" window is shown where more complicated selections are needed
  • Problems pane is populated with errors
  • Color output
  • Available commands:
    • PHPUnit Test
      • Tries to do the right thing (test class/method where cursor is or suite if file is phpunit.xml)
    • PHPUnit Test Nearest
    • PHPUnit Test Suite
    • PHPUnit Test Directory
    • PHPUnit Rerun Last Test
    • PHPUnit Stop Running Tests

Manual setup

  • Install phpunit in your workspace.
  • Common config options:
{
    "phpunit.php": "path/to/php",           // Skip to use php in env path
    "phpunit.phpunit": "path/to/phpunit",   // Skip to find in common places (vendor, *.phar)
    "phpunit.args": [
        "-c", "./phpunit.xml.dist"          // Any args, check `phpunit --help`
    ],
    "phpunit.paths": {                      // Map paths in remote environments.
        "/local/path": "/remote/path",      // ${workspaceFolder} is replaced as in tasks.json
        "${workspaceFolder}": "/remote/app"
    }
}

Zero config needed if you have php or docker in you environment path and phpunit in your project (composer vendor dir or *.phar file). See the configuration section in package.json for all values and their descriptions (highly recommened if you need advanced functionality).

Remote configs

For docker, vagrant, laravel-homestead, WSL or any other virtual/remote environment, please consider the Remote Development extension by Mircosoft. VSCode will run agains a remote directory and you can simply run your tests as you would locally.

Manual ssh

{
    "phpunit.ssh": "ssh root@localhost \"<command>\"",  // ssh command to connect to remote machine.
    "phpunit.paths": {
        "/local/path": "/remote/path",
        "${workspaceFolder}": "/app"
    }
}

<command> is populated by the extension. The final command could then be something like ssh root@localhost "php ./phpunit.phar -c phpunit.xml" depending on your settings.

Setup public/private keys (passwords won't work):
- Windows powershell ssh-keygen && cat $env:userprofile/.ssh/id_rsa.pub | ssh root@localhost 'cat >> .ssh/authorized_keys'
- Linux bash ssh-keygen && ssh-copy-id root@localhost

OpenSSH (ssh and ssh-keygen) is available on windows since late 2018. It's easy to install with powershell if it's not enabled.

Manual docker container

{
    "phpunit.docker.container": "container_name",   // Skip to select from running containers
    "phpunit.paths": {
        "${workspaceFolder}": "/app"                // Map your ${workspaceFolder} to where it
    }                                               // is in your container. Ex: /app
}

Manual docker image

{
    "phpunit.command": "docker run --rm -t -v ${pwd}:/app -w /app php:latest php",
    "phpunit.paths": {                  // ${pwd} (current directory) is mounted to /app
        "${workspaceFolder}": "/app"    // ${workspaceFolder} is mapped to /app
    }
}

Manual docker-compose service

{
    "phpunit.command": "docker-compose run --rm service_name",
    "phpunit.paths": {
        "${workspaceFolder}": "/app"                // Map your ${workspaceFolder} to where it
    }                                               // is in your container. Ex: /app
}

Examples

Run with (Cmd+Shift+P on OSX or Ctrl+Shift+P on Windows and Linux) and execute the PHPUnit Test command.

  • Test a function: Place cursor on a function and run.

Cara menggunakan phpunit expectexceptionmessagematches

  • Test a class: Place cursor on class name and run.

Cara menggunakan phpunit expectexceptionmessagematches

  • Pick test from a list: Place cursor anywhere in class except on class name or on a function and run.

Cara menggunakan phpunit expectexceptionmessagematches

  • Test everything according to --configuration: Close editor window and run.

Cara menggunakan phpunit expectexceptionmessagematches

  • Test everything in a directory: Open a file in the directory to test and run the PHPUnit Test Directory command.

Cara menggunakan phpunit expectexceptionmessagematches

  • Rerun last Test: Run the PHPUnit Rerun Last Test command.

Keybinding example:

{ "key": "cmd+shift+t", "command": "phpunit.Test", "when": "editorFocus" }