PHPunit to test catch block - php

I have a code like this one:
public function one()
{
try {
$this->two();
} catch (Exception $E) {
$this->three();
}
}
How can i test that $this->three() function is called?
I've tried to "mock by code" $this->two() and throw error instead of it's original code, but that ends up with error caught by phpunit itself.
Tried setExpectedException, but it also doesn't solve the problem - catch runs inside phpunit again and just ignored.
Function $this->three() never called in both cases.
Thanks!

The problem was that the described method were in a class which was placed in a namespace containing it's own Exception implementation. So I was catching an \Namespace\Exception while throwing an \Exception.
Throwing correct exception did the thing.
#sectus, thank you!

Related

PHPUnit try catch does not work in a test case

I tried to catch an exception inside a PHPUnit test but it does not work as I expected. The exception seems to be caught in a higher level and I do not understand why.
public function testException()
{
echo 'Enter';
try {
throw new Exception('error.');
} catch (Exception $e) {
echo 'catch Exception';
}
echo 'End';
}
In the output only 'Enter' is visible. I do not reach the 'End'.
(I am using PHP7)
Thanks
Edit:
Replacing all Exception with \Exception solved my issue
Handling exceptions can be tricky, especially when they are called Exception :-)
Just look at all the feedback this (almost the same) question has generated.
Now, the exception is not caught only if does not match to the expected class. In this case it is definitely because of non-precise Exception class names specification, which will most certainly be fixed by specifying them as \Exception.
As smartly put by a commenter from the mentioned question thread:
Without the backslash Exception is specific to the namespace and won't be matched (or caught).

PHPUnit Mocked method causes an exception

I have this function in a class
public function doSomething()
{
try {
$result = functionCall();
if ($result === true) {
$this->doGoodResult('With Success Message');
} else {
$this->doBadResult('ERROR - unable to do something');
}
} catch (Exception $e) {
$this->doBadResult('Did you divide by zero?');
}
}
and I'm trying to test it with mocking out the extra functions
public function test_doSomthingWithBadResultGetsDoBadResultCalled()
{
$ajc = $this->getMockBuilder('MyClass')
->setMethods(array('doBadResult'))
->setConstructorArgs(array('doSomething', array('input_var' => 0)))
->getMock();
$ajc->expects($this->once())
->method('doBadResult')
->willReturn(null)
->with($this->contains('ERROR - unable to do something'));
$ajc->doSomething();
}
and the problem is that I'm getting the following error from PHPUnit
MyClass::doBadResult('Did you divide by zero?') was not expected to be called more than once.
I'm not sure why, but it looks like the catch statement is being executed only when in this mock scenario.
Could anyone help me figure out why this is happening and especially how to set this up so that my test doesn't fail?
After some debugging I found the Exception was Invalid argument supplied for foreach() and after some digging, it was in the $this->contains('ERROR...')
the answer is $this->contains should be $this->stringContains
To prevent your need to do more digging in the future. One of the problems that you have in your code is that you are catching the Base Exception type.
} catch (Exception $e) {
$this->doBadResult('Did you divide by zero?');
}
When an assertion fails in PHPUnit, a PHPUnit_Framework_AssertionFailedError is thrown and is caught by PHPUnit. This error extends the Base PHP Exception class. So inside your try block when the mock object gets called, it checks the parameters that were used. Since these are not correct, it throws the PHPUnit_Framework_AssertionFailedError which your catch statement grabs. Which then calls the method on your mock that wasn't expected to be called.
Because of this, it would be possible for your test to end up passing incorrectly. Because the failed assertion gets caught and handled by your code. You should have a specific exception that your catch is looking for and any other exceptions get passed on to the appropriate level.

Exception not bubbling up from parent constructor

My exception does not seem to be bubbling up from the parent constructor.
Here's a simplified version:
class importer {
public function __construct()
{
$this->getFile(); // fills out $file with name or false on failure
if (!$this->file) {
throw new Exception("Sorry no file, so no can do!");
}
}
}
class childImporter extends importer {
pubclic function __construct()
{
parent::__construct();
}
}
try {
new childImporter();
nextFunction();
} catch (Exception $e) {
echo $e->getMessage();
}
nextFunction never gets called, and the catch block doesn't get run either, the whole thing throws an uncaught exception fault and stops.
I thought exceptions were supposed to bubble up?
Or is the code above supposed to work and something else is going wrong?
So for anyone else having a similar issue the problem was, as cbuckley pointed out, an issue with namespacing.
I changed both occurrences of Exception to \Exception which caught it nicely.
I wasn't getting any other namespace errors in my ide as PHPStorm had very nicely auto-imported an exception class of Symfony\Component\Config\Definition\Exception\Exception from who knows where (as I am not using any Symfony components anywhere else!).
Hope this helps someone who has also had a really long day!

Why isn't my Exception being caught by catch?

I have some code that looks like this
# Try to import file
try
{
DataManager::fileImport($_FILES['datafile']['tmp_name'],
$_POST['zones'], $_POST['statuses']);
}
catch(Exception $e)
{
print 'Herp.';
$response->body = Helpers::getVarDump($e);
}
DataManager::fileImport is literally a one-line function that throws a normal Exception:
static function fileImport($filepath, $zones, $statuses)
{
throw new Exception('SOME EXCEPTION');
}
And yet I get
Fatal error: Uncaught exception 'Exception' with message 'SOME EXCEPTION'...
From the try block. Also 'Herp.' is never printed. Why doesn't the Exception trigger the catch block?
EDIT: I should mention I'm using Tonic and PHP 5.3.9
EDIT AGAIN: Here's DataManager (with names replaced with ... for anonymity) http://pastebin.com/daHWBJDC
Solution
I neglected to specify use \Exception; in the file containing the try/catch.
Pondering
I know it's intentional that each namespace in PHP should define its own Exception for many reasons, but I still find it odd that catch(Exception e) didn't cause any errors when Exception in that context wasn't defined. If I were to write new Exception() I would get an error.
Oh well, at least I learned something.
Strange. If i run this code i get the "Herp."
<?php
class DataManagerTest {
static function fileImport($filepath, $zones, $statuses)
{
throw new Exception('SOME EXCEPTION');
}
}
# Try to import file
try
{
DataManagerTest::fileImport("param1","param2","param3");
}
catch(Exception $e)
{
print 'Herp.';
}
?>
You might have an issue with your DataManager class because i copied your code, adapted it to run and i get the exception handled... You problem is elsewhere...
class DataManager {
static function fileImport($filepath, $zones, $statuses){
throw new Exception('SOME EXCEPTION');
}
}
try{
DataManager::fileImport('', '', '');
}catch(Exception $e){
print 'Herp.';
}
Results in
Herp.
4 years later...
#Hubro, thank you for saving me with that namespace fix!
It does seem counterintuitive at first that it's necessary when throwing a root-level Exception, even though it ultimately makes sense in the general context of namespaces.
For anyone who doesn't want to utilize #Hubro's file-level fix:
use \Exception;
You could instead add the backslash in front of Exception in the higher level catch block:
} catch (\Exception $e) {
We could all benefit from someone smarter than me providing suggestions on best practices around defining a custom Exception for each namespace. Any takers?

PHPUnit stub throws exception but isn't allowed to be caught

I'm trying to test a try/catch block using a stub that throws an exception when a certain method create is called. It works fine, the exception is raised, but instead of my application catching it, it stops the execution of the test. What is some better ways to go about doing this.
<?php
// TestCase
$mockDao->expects($this->once())
->method('create')
->will($this->throwException(new \Exception));
$service->addEntity($data);
?>
<?php
// Service
public function addEntity($data)
{
....
try {
...
$this->create($entity); // Test Halts with Exception
...
} catch (Exception $e) {
// Never Gets Called
$this->handleException($e);
}
}
You are throwing \Exception but catching Exception. Is the class that implements addEntity() in a namespace? Does changing it to catch \Exception fix the problem? If not, try changing the test to throw Exception.

Categories