Skip to content

Commit 2e30869

Browse files
author
Gustavo Nieves
authored
Added assertDoesNotThrow* assertions (and more) (#11)
* optimized code, added assertDoesNotThrow assertions, updated tests and phpunit versions. * Allow to test functions with parameters
1 parent ab1622f commit 2e30869

File tree

8 files changed

+250
-93
lines changed

8 files changed

+250
-93
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ composer.phar
22
/vendor/
33
.idea
44
composer.lock
5+
.phpunit.result.cache
56

67
# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
78
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
language: php
22

33
php:
4-
- 7
54
- 7.1
65
- 7.2
6+
- 7.3
7+
- 7.4
78

89
cache:
910
directories:
@@ -15,4 +16,4 @@ sudo: false
1516
before_install:
1617
- composer update --prefer-source
1718

18-
script: vendor/bin/phpunit tests
19+
script: vendor/bin/phpunit

AssertThrows.php

Lines changed: 137 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,178 @@
1-
<?php
1+
<?php declare(strict_types=1);
22

33
namespace Codeception;
44

5+
use PHPUnit\Framework\Assert;
56
use PHPUnit\Framework\AssertionFailedError;
6-
use PHPUnit\Framework\TestCase;
7+
use Throwable;
78

89
trait AssertThrows
910
{
11+
/**
12+
* @param string|null $message
13+
* @param Throwable $exception
14+
*/
15+
private function checkException(?string $message, Throwable $exception)
16+
{
17+
$actualMessage = strtolower($exception->getMessage());
18+
19+
if (!$message || $message === $actualMessage) {
20+
return;
21+
}
22+
23+
throw new AssertionFailedError(
24+
sprintf(
25+
"Exception message '%s' was expected, but '%s' was received",
26+
$message,
27+
$actualMessage
28+
)
29+
);
30+
}
1031

1132
/**
1233
* Asserts that callback throws an exception
1334
*
1435
* @param $throws
15-
* @param callable $fn
16-
* @throws \Exception
36+
* @param callable $func
37+
* @param mixed ...$params
38+
* @throws Throwable
1739
*/
18-
public function assertThrows($throws, callable $fn)
40+
public function assertThrows($throws, callable $func, ...$params)
1941
{
20-
$this->assertThrowsWithMessage($throws, false, $fn);
42+
$this->assertThrowsWithMessage($throws, null, $func, $params);
2143
}
2244

2345
/**
2446
* Asserts that callback throws an exception with a message
2547
*
26-
* @param $throws
27-
* @param $message
28-
* @param callable $fn
48+
* @param string|Throwable $throws
49+
* @param string|null $message
50+
* @param callable $func
51+
* @param mixed ...$params
52+
* @throws Throwable
2953
*/
30-
public function assertThrowsWithMessage($throws, $message, callable $fn)
54+
public function assertThrowsWithMessage($throws, ?string $message, callable $func, ...$params)
3155
{
32-
/** @var $this TestCase * */
33-
$result = $this->getTestResultObject();
34-
35-
if (is_array($throws)) {
36-
$message = ($throws[1]) ? $throws[1] : false;
37-
$throws = $throws[0];
56+
if ($throws instanceof Throwable) {
57+
$message = $throws->getMessage();
58+
$throws = get_class($throws);
3859
}
3960

40-
if (is_string($message)) {
61+
if ($message) {
4162
$message = strtolower($message);
4263
}
4364

4465
try {
45-
call_user_func($fn);
46-
} catch (AssertionFailedError $e) {
66+
if ($params) {
67+
call_user_func_array($func, $params);
68+
} else {
69+
call_user_func($func);
70+
}
71+
} catch (AssertionFailedError $exception) {
4772

48-
if ($throws !== get_class($e)) {
49-
throw $e;
73+
if ($throws !== get_class($exception)) {
74+
throw $exception;
5075
}
5176

52-
if ($message !== false && $message !== strtolower($e->getMessage())) {
53-
throw new AssertionFailedError("Exception message '$message' was expected, but '" . $e->getMessage() . "' was received");
77+
$this->checkException($message, $exception);
78+
79+
} catch (Throwable $exception) {
80+
81+
if (!$throws) {
82+
throw $exception;
5483
}
5584

56-
} catch (\Exception $e) {
57-
if ($throws) {
58-
if ($throws !== get_class($e)) {
59-
throw new AssertionFailedError("Exception '$throws' was expected, but " . get_class($e) . " was thrown with message '" . $e->getMessage() . "'");
60-
}
85+
$actualThrows = get_class($exception);
6186

62-
if ($message !== false && $message !== strtolower($e->getMessage())) {
63-
throw new AssertionFailedError("Exception message '$message' was expected, but '" . $e->getMessage() . "' was received");
64-
}
65-
} else {
66-
throw $e;
87+
if ($throws !== $actualThrows) {
88+
throw new AssertionFailedError(
89+
sprintf(
90+
"Exception '%s' was expected, but '%s' was thrown with message '%s'",
91+
$throws,
92+
get_class($exception),
93+
$exception->getMessage()
94+
)
95+
);
6796
}
97+
98+
$this->checkException($message, $exception);
6899
}
69100

70-
if ($throws) {
71-
if (isset($e)) {
72-
$this->assertTrue(true, 'exception handled');
101+
if (!$throws) {
102+
return;
103+
}
104+
105+
if (isset($exception)) {
106+
Assert::assertTrue(true, 'Exception handled');
107+
return;
108+
}
109+
110+
throw new AssertionFailedError(
111+
sprintf("Exception '%s' was not thrown as expected", $throws)
112+
);
113+
}
114+
115+
/**
116+
* Asserts that callback does not throws an exception
117+
*
118+
* @param null|string|Throwable $throws
119+
* @param callable $func
120+
* @param mixed ...$params
121+
*/
122+
public function assertDoesNotThrow($throws, callable $func, ...$params)
123+
{
124+
$this->assertDoesNotThrowWithMessage($throws, null, $func, $params);
125+
}
126+
127+
/**
128+
* Asserts that callback does not throws an exception with a message
129+
*
130+
* @param null|string|Throwable $throws
131+
* @param string|null $message
132+
* @param callable $func
133+
* @param mixed ...$params
134+
*/
135+
public function assertDoesNotThrowWithMessage($throws, ?string $message, callable $func, ...$params)
136+
{
137+
if ($throws instanceof Throwable) {
138+
$message = $throws->getMessage();
139+
$throws = get_class($throws);
140+
}
141+
142+
try {
143+
if ($params) {
144+
call_user_func_array($func, $params);
73145
} else {
74-
throw new AssertionFailedError("Exception '$throws' was not thrown as expected");
146+
call_user_func($func);
75147
}
76-
}
148+
} catch (Throwable $exception) {
149+
if (!$throws) {
150+
throw new AssertionFailedError('Exception was not expected to be thrown');
151+
}
152+
153+
$actualThrows = get_class($exception);
77154

155+
if ($throws != $actualThrows) {
156+
Assert::assertNotSame($throws, $actualThrows);
157+
return;
158+
}
159+
160+
if (!$message) {
161+
throw new AssertionFailedError(
162+
sprintf("Exception '%s' was not expected to be thrown", $throws)
163+
);
164+
}
165+
166+
$actualMessage = $exception->getMessage();
167+
168+
if ($message != $actualMessage) {
169+
Assert::assertNotSame($message, $actualMessage);
170+
return;
171+
}
172+
173+
throw new AssertionFailedError(
174+
sprintf("Exception '%s' with message '%s' was not expected to be thrown", $throws, $message)
175+
);
176+
}
78177
}
79178
}

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2017 Codeception Testing Framework
3+
Copyright (c) 2020 Codeception Testing Framework
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Readme.md

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,60 @@
11
# AssertThrows
22

3+
Handle exceptions inside a test without a stop! Works with PHPUnit and Codeception.
4+
35
[![Build Status](https://travis-ci.org/Codeception/AssertThrows.svg?branch=master)](https://travis-ci.org/Codeception/AssertThrows)
46

5-
Handle exceptions inside a test without a stop!
7+
## Installation
68

7-
---
9+
```
10+
composer require codeception/assert-throws --dev
11+
```
812

9-
Assertions for exceptions. Works with PHPUnit and Codeception.
13+
Include `AssertThrows` trait it to a TestCase:
14+
15+
```php
16+
<?php
17+
18+
class MyTest extends PHPUnit\Framework\TestCase
19+
{
20+
use Codeception\AssertThrows;
21+
22+
//...
23+
}
24+
```
1025

1126
## Usage
1227

1328
Catch exception thrown inside a code block.
1429

1530
```php
1631
<?php
32+
1733
$this->assertThrows(NotFoundException::class, function() {
18-
$this->userController->show(999);
34+
$this->userController->show(99);
1935
});
2036

2137
// alternatively
22-
$this->assertThrows(new NotFoundException, function() {
23-
$this->userController->show(999);
38+
$this->assertThrows(new NotFoundException(), function() {
39+
$this->userController->show(99);
2440
});
25-
?>
26-
```
2741

28-
You can optionally test the exception message:
29-
30-
```php
31-
<?php
32-
$this->assertThrowsWithMessage(NotFoundException::class, 'my error message', function() {
33-
throw new NotFoundException('my error message');
42+
// you can also assert that an exception is not throw
43+
$this->assertDoesNotThrow(NotFoundException::class, function() {
44+
$this->userController->show(99);
3445
});
35-
?>
3646
```
3747

38-
### Installation
39-
40-
```php
41-
composer require codeception/assert-throws --dev
42-
```
43-
44-
Include `AssertThrows` trait it to a TestCase:
48+
You can optionally test the exception message:
4549

4650
```php
4751
<?php
48-
class MyTest extends PHPUnit\Framework\TestCase
49-
{
50-
use Codeception\AssertThrows;
5152

52-
}
53+
$this->assertThrowsWithMessage(
54+
NotFoundException::class, 'my error message', function() {
55+
throw new NotFoundException('my error message');
56+
}
57+
);
5358
```
5459

55-
## License MIT
60+
### License MIT

composer.json

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@
22
"name": "codeception/assert-throws",
33
"description": "Assert exception was thrown without stopping a test",
44
"type": "library",
5-
"require": {
6-
"phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0"
7-
},
85
"license": "MIT",
9-
"autoload": {
10-
"psr-4": {
11-
"Codeception\\": "./"
12-
}
13-
},
146
"authors": [
157
{
168
"name": "davert",
179
"email": "[email protected]"
10+
},
11+
{
12+
"name": "Gustavo Nieves",
13+
"homepage": "https://medium.com/@ganieves"
1814
}
19-
]
15+
],
16+
"require": {
17+
"phpunit/phpunit": "^7.5|^8.0|^9.0"
18+
},
19+
"autoload": {
20+
"psr-4": {
21+
"Codeception\\": "./"
22+
}
23+
}
2024
}

phpunit.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<phpunit colors="true">
2+
<testsuites>
3+
<testsuite name="AssertThrows">
4+
<directory>tests</directory>
5+
</testsuite>
6+
</testsuites>
7+
</phpunit>

0 commit comments

Comments
 (0)