3

I have div() in Cal class in my CalTest class has following methods to test the div().

public fucnction div($a,$b){
   if($b == 0){
    throw new Exception("Divided by zero");
   }
   return $a/$b
}

I can pass only testDiv() but testDiv2().

enter image description here

I want to catch check wheather the exeption thrown correctly using PHPUnit. What am I missing here?? Your help is highly appreciated. Thank you!

enter image description here

7
  • possible duplicate of PHPUnit assert that an exception was thrown?
    – Corbin
    Commented May 4, 2012 at 11:05
  • Hmm, it looks like you have the annotation correct, actually (so perhaps not a duplicate). Have you tried removing the tabs between the annotation @ and the exception name? Edit: Actually, I think the problem is that your expectedMessage is not the exception message.
    – Corbin
    Commented May 4, 2012 at 11:07
  • @Corbin I read that question and tried it and Tried with different exceptions . But no result
    – Ruwantha
    Commented May 4, 2012 at 11:09
  • Does PHPUnit automatically catch exceptions? Do you not have to do a try/catch block?
    – Anthony
    Commented May 4, 2012 at 11:47
  • @Anthony No, you do it in the comment block as RJ has done.
    – vascowhite
    Commented May 5, 2012 at 6:42

6 Answers 6

4

Your 2nd screenshot (the one with the error) has

"@expectedException Exception"

while the third has

@expectedException InvalidArgumentException

Do you really still get the error? Did you save the file?


Works for me:

Foo.php

<?php

class Foo
{
    static function t()
    {
        throw new InvalidArgumentException('Hi there');
    }
}

?>

FooTest.php

<?php
require_once 'Foo.php';
class FooTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testT()
    {
        Foo::t();
    }
}

?>

Result

$ phpunit .
PHPUnit 3.6.10 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 5.25Mb

OK (1 test, 1 assertion)
7
  • yes, that's true. That's because I tried both ways while I taking the screen shots(both are not working). sorry for the that.
    – Ruwantha
    Commented May 5, 2012 at 2:03
  • Your functions are working perfectly. But in my case it still says invalidAargumetExepetion
    – Ruwantha
    Commented May 7, 2012 at 4:32
  • Then please post minimal code that reproduces your problem. I'm sure the problem is on your side.
    – cweiske
    Commented May 7, 2012 at 4:57
  • yes problem is on my side. Only the testDiv2() is troubling me not the other one so I guess it's the minimal code for my problem.
    – Ruwantha
    Commented May 7, 2012 at 6:15
  • no, I mean code that I can copy&paste to reproduce your problem on my machine.
    – cweiske
    Commented May 7, 2012 at 11:32
3

Just came across the same issue. For some reason PHPUnit will not allow you to set the expectedException to a generic exception and I am not sure why. Personally I opt to throw custom Exception codes rather than have to create a new exception class every time I want to differentiate exceptions.

Here is how I got around it:

/**
 * @expectedException Test_Exception
 */
public function testDivByZero()
{
    try {
        // Fyi you don't need to do an assert test here, as we are only testing the exception, so just make the call
        $result = $this->object->div(1,0);
    } catch (Exception $e) {
        if ('Exception' === get_class($e)) {
            throw new Test_Exception($e->getMessage(), $e->getCode());
        }
    }
 }

 // Test_Exception.php
 class Test_Exception extends Exception
 {
     public function __construct($message = null, $code = 0, Exception $previous = null)
     {
         parent::__construct($message, $code, $previous);
     }
 }

This will allow you to engineer your code the way you want, and throw "generic" exceptions. Basically it just tests the Exception class and if it's generic, re-wrap it as a different exception; Test_Exception.

-- Update --

Found out yesterday that they have removed the generic exception restriction in the current "master" branch, which will be 3.7. Apparently the lead engineer has no desire of patching 3.6.

2

This problem has been fixed in PHPUnit 3.7.x

You can use the following Generic Exception in PHPUnit 3.7.x

    /**
     * @expectedException Exception     
     */
2

It says so in the exception thrown by PHPUnit:

You must not except the generic exception class.

Make your class throw more detailed Exceptions, and further specify the exception type your expecting in your unit test.

5
  • Even I expect InvalidArgumentException it is not working. I think it is not generic exception class , right ??
    – Ruwantha
    Commented May 4, 2012 at 11:41
  • You are throwing a generic exception though aren't you?
    – vascowhite
    Commented May 4, 2012 at 11:46
  • @vascowhite : what should I do then shall I throw InvalidArgumentException then ?
    – Ruwantha
    Commented May 5, 2012 at 2:06
  • If that's what your telling PHPUnit to expect, then its logical that that is what you should be throwing isn't it?
    – vascowhite
    Commented May 5, 2012 at 6:43
  • 2
    This is a terrible suggestion. Having a vendor API dictate how to engineer code is a bad practice. IMO PHPUnit dropped the ball on this one. Some of us opt for exception codes rather than throwing custom exceptions. Commented May 24, 2012 at 20:07
0

you can do something like this

write your unit test so you inject the values required to trigger the exception then

//assert $this->assertTrue($this->setExpectedException('PHPUnit_Framework_ExpectationFailedException'));

2
  • 1
    I'm not clear with what you said, Are you telling met to insert this code to testDiv() or something else ? I tried that after you tall but still the same :'(
    – Ruwantha
    Commented May 7, 2012 at 4:16
  • I dont understand your comment, but i would suggest using the phpunit resources. phpunit.de/manual/3.2/en/…
    – jsteinmann
    Commented Nov 26, 2012 at 2:05
0

I create a parent class method to do it. In fact, this class came from the laravel but is valid in any context.

The cool part of this method is using anonymous functions into PHP

<?php
class TestCase 
         /* if you are not using laravel, you dont need this 
        extends Illuminate\Foundation\Testing\TestCase */ {

    protected function assertThrows( $function , $classException = "/Exception" )
    {
        try 
        {
            // Anonymous functions FTW
            $function();
        }
        catch( /Exception $objException )
        {
            // the assertInstanceOf should solve from here but
            // it is not working that great
            // @see http://stackoverflow.com/questions/16833923/phpunit-assertinstanceof-not-working
            if( $objException instanceof $classException ) {
                return $this->assertTrue( true );
            } else {
                // this will throw a error with a cool message
                return $this->assertEquals( $classException  , get_class( $objException ));
            }
        }
        // no exception happened.
        return $this->fail( "Exception " . $classException . " expected." );
    }

}

class LanguageTest extends TestCase {

    /**
     * Test the translation
     *
     * @return void
     */
    public function testTranslation()
    {
        // this test may be ok
        $this->assertThrows( 
            function(){ throw new Full\Path\Exception(":("); }, 
            "Full\Path\Exception" );

        // this test may fail 
        $this->assertThrows( 
            function(){ return 1 + 1; }, 
            "Some\Excepted\Exception" );

        // this test may work 
        $this->assertThrows( 
            function(){ throw new Exception( "sad" ); }
        );
    }

} 

Not the answer you're looking for? Browse other questions tagged or ask your own question.