Skip to content

Commit 72ad019

Browse files
committed
feat(test): Add the ability to assert that an exception is thrown
1 parent 4625750 commit 72ad019

File tree

1 file changed

+110
-11
lines changed

1 file changed

+110
-11
lines changed

tests/DoctrineTest/UnitTestCase.php

Lines changed: 110 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ class UnitTestCase
1111

1212
protected static $_lastRunsPassesAndFails = array('passes' => array(), 'fails' => array());
1313

14+
/**
15+
* @var string
16+
*/
17+
private $_expectedExceptionClass;
18+
19+
/**
20+
* @var string
21+
*/
22+
private $_currentMethod;
23+
1424
public function setUp()
1525
{
1626
}
@@ -19,6 +29,11 @@ public function tearDown()
1929
{
2030
}
2131

32+
protected function expectException($class)
33+
{
34+
$this->_expectedExceptionClass = $class;
35+
}
36+
2237
public function init()
2338
{
2439
$tmpFileName = $this->getPassesAndFailsCachePath();
@@ -70,6 +85,15 @@ public function assertIdentical($value, $value2)
7085
}
7186
}
7287

88+
public function assertNotIdentical($value, $value2)
89+
{
90+
if ($value !== $value2) {
91+
$this->pass();
92+
} else {
93+
$this->_fail();
94+
}
95+
}
96+
7397
public function assertNotEqual($value, $value2)
7498
{
7599
if ($value != $value2) {
@@ -126,41 +150,75 @@ public function pass()
126150

127151
public function fail($message = "")
128152
{
129-
$this->_fail($message);
153+
$this->_fail($message);
130154
}
131155

132156
public function _fail($message = "")
157+
{
158+
$stack = $this->findTestMethodStack();
159+
160+
$this->appendMessage($stack['class'], $stack['method'], $stack['line'], $message);
161+
162+
$this->_failed++;
163+
164+
$class = get_class($this);
165+
166+
if (isset(self::$_passesAndFails['passes'][$class])) {
167+
unset(self::$_passesAndFails['passes'][$class]);
168+
}
169+
170+
self::$_passesAndFails['fails'][$class] = $class;
171+
}
172+
173+
private function findTestMethodStack()
133174
{
134175
$trace = debug_backtrace();
135176
array_shift($trace);
136177

137-
138178
foreach ($trace as $stack) {
139-
if (substr($stack['function'], 0, 4) === 'test') {
179+
if ($this->isTestMethod($stack['function'])) {
140180
$class = new ReflectionClass($stack['class']);
141181

142182
if ( ! isset($line)) {
143183
$line = $stack['line'];
144184
}
145185

146-
$errorMessage = $class->getName() . ' : method ' . $stack['function'] . ' failed on line ' . $line;
147-
$this->_messages[] = $errorMessage . " " . $message;
148-
break;
186+
return array(
187+
'class' => $class->getName(),
188+
'method' => $stack['function'],
189+
'line' => $line,
190+
);
149191
}
192+
150193
$line = $stack['line'];
151194
}
152-
$this->_failed++;
153-
$class = get_class($this);
154-
if (isset(self::$_passesAndFails['passes'][$class])) {
155-
unset(self::$_passesAndFails['passes'][$class]);
195+
196+
return array(
197+
'class' => get_class($this),
198+
'method' => $this->_currentMethod,
199+
'line' => null,
200+
);
201+
}
202+
203+
private function appendMessage($testCase, $testFuntion, $line = null, $message = "")
204+
{
205+
$lineMessage = '';
206+
207+
if (null !== $line) {
208+
$lineMessage = 'on line '.$line;
156209
}
157-
self::$_passesAndFails['fails'][$class] = $class;
210+
211+
$errorMessage = $testCase . ' : method ' . $testFuntion . ' failed '.$lineMessage;
212+
213+
$this->_messages[] = $errorMessage . " " . $message;
158214
}
159215

160216
public function run(DoctrineTest_Reporter $reporter = null, $filter = null)
161217
{
162218
foreach (get_class_methods($this) as $method) {
163219
if ($this->isTestMethod($method)) {
220+
$this->_currentMethod = $method;
221+
164222
$this->runTest($method);
165223
}
166224
}
@@ -294,8 +352,49 @@ private function tryFinally(Closure $try, Closure $finally)
294352

295353
$finally();
296354

355+
if (null !== $this->_expectedExceptionClass) {
356+
$this->assertThrownException($thrownException);
357+
358+
return;
359+
}
360+
297361
if (null !== $thrownException) {
298362
throw $thrownException;
299363
}
300364
}
365+
366+
private function assertThrownException($thrownException)
367+
{
368+
$expectedExceptionClass = $this->_expectedExceptionClass;
369+
370+
$this->_expectedExceptionClass = null;
371+
372+
if (null === $thrownException) {
373+
$message = sprintf('Assert that exception "%s" is thrown.',
374+
$expectedExceptionClass
375+
);
376+
377+
$this->fail($message);
378+
379+
return;
380+
}
381+
382+
$thrownExceptionClass = get_class($thrownException);
383+
384+
if (
385+
$expectedExceptionClass === $thrownExceptionClass
386+
|| is_subclass_of($thrownExceptionClass, $expectedExceptionClass)
387+
) {
388+
$this->pass();
389+
390+
return;
391+
}
392+
393+
$message = sprintf('Assert that exception "%s" is thrown, but was "%s".',
394+
$expectedExceptionClass,
395+
$thrownExceptionClass
396+
);
397+
398+
$this->fail($message);
399+
}
301400
}

0 commit comments

Comments
 (0)