如何测试每一行是否抛出相同的异常?

I want to test that my function refuses all non-positive integers. It throws an InvalidArgumentException. I wrote a test like this:

/**
 * @test
 * @expectedException InvalidArgumentException
 */
public function testXThrowsException()
{
    $this->parser->x(1.5);
    $this->parser->x('2');
    $this->parser->x(1000E-1);
    $this->parser->x(+100);
}

My test always passes because the first one throws an exception. The others don't get tested properly. I can add $this->parser->x(1); to my code and it would still pass.

What should I do to assert that all these function calls raise the InvalidArgumentException?

/**
 * @test
 * @expectedException InvalidArgumentException
 *
 * @dataProvider foo
 */
public function testXThrowsException($value)
{
    $this->parser->x($value);
}

/**
 * Test data
 * Returns array of arrays, each inner array is used in
 * a call_user_func_array (or similar) construction
 */
public function foo()
{
    return array(
        array(1.5),
        array('2'),
        array(1000E-1),
        array(+100)
    );
}

A solution would be to use it like this:

/**
 * @test
 */
public function testXThrowsException()
{
    try {
        $this->parser->x(1.5);
        $this->fail('message');
    } catch (InvalidArgumentException $e) {}
    try {
        $this->parser->x('2');
        $this->fail('message');
    } catch (InvalidArgumentException $e) {}
    try {
        $this->parser->x(1000E-1);
        $this->fail('message');
    } catch (InvalidArgumentException $e) {}
    try {
        $this->parser->x(+100);
        $this->fail('message');
    } catch (InvalidArgumentException $e) {}

}

Now you can test every line on its own. Whenever method x() does not raise an exception, the test fails using fail().

If you have alot of negative values you could also put them in an array, and loop over the array with the following code (without testing):

foreach($wrongValueArray as $failtyValue) { 
  try { $this->parser->x($failtyValue); 
      this->fail($failtyValue . ' was correct while it should not'); 
  } catch (InvalidArgumentException $e) {} 
}

It's a bit shorter