Create mock for class with dangerous constructor
You want to:
Create a mock, but the mocked class has a constructor that
executes sudo rm -Rf /, accesses a database, or otherwise
causes trouble for your unit tests.
Solution:
Pass in an optional boolean fifth argument to $this->getMock().
$this->getMock() takes as a fifth argument a boolean
that indicates whether PHPUnit should call the original constructor
when constructing the mocked out class, which defaults to
TRUE. If set to FALSE, the constructor won't
be called. In that case, you can also pass an empty array as
constructor arguments (the third argument to
$this->getMock()), since they won't be used anyway.
Of course, you can also refactor the code to not do as much in its constructor. Quite often, there's a way to structure the code differently so that it is more loosely coupled and easier to test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?php
require_once "PHPUnit/Framework.php";
class FilesMultiplier
{
/*
* Read a pair of numbers from a file, mutiply, and return.
*/
public function multiply($inputFile)
{
$line = $inputFile->read();
$parts = explode(" ", $line);
$a = (integer) $parts[0];
$b = (integer) $parts[1];
$result = ($a * $b);
return $result;
}
}
class FileObject
{
public function __construct($filename)
{
// This exception represents our "dangerous" code.
throw new Exception("Danger, Will Robinson");
}
/*
* This function reads a line from a file.
*/
public function read()
{
// ... code omitted
}
}
class TestFilesMultiplier extends PHPUnit_Framework_TestCase
{
public function test_multiply()
{
$multiplier = new FilesMultiplier();
$inputFile = $this->getMock('FileObject',
array('read'),
array(),
'FileObject_test_multiply',
FALSE);
$inputFile->expects($this->once())
->method('read')
->will($this->returnValue("3 4"));
$result = $multiplier->multiply($inputFile);
$this->assertEquals($result, 12,
"Multiplying 3 by 4 did not give 12 as expected.");
}
}
?>
