5

I try to make unit test of a custom Exception Handler class (located in app/Exceptions/Handler.php), but i don't know how to do it ...

I don't know how to raise an exception with my mock Request.

Is someone can help me ?

Here is the "render" method :

/**
 * @param \Illuminate\Http\Request $request
 * @param Exception $e
 * @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\Response
 */
public function render($request, Exception $e)
{
    // This will replace our 404 response with
    // a JSON response.
    if ($e instanceof ModelNotFoundException &&
        $request->wantsJson()) {
        Log::error('render ModelNotFoundException');
        return response()->json([
            'error' => 'Resource not found'
        ], 404);
    }
    if ($e instanceof TokenMismatchException) {
        Log::error('render TokenMismatchException');
        return new RedirectResponse('login');
    }
    if ($e instanceof QueryException) {
        Log::error('render QueryException', ['exception' => $e]);
        return response()->view('errors.500', ['exception' => $e, 'QueryException' => true],500);
    }

    return parent::render($request, $e);
}

And this is my test case :

/**
 * @test
 */
public function renderTokenMismatchException()
{
    $request = $this->createMock(Request::class);
    $request->expects($this->once())->willThrowException(new TokenMismatchException);
    $instance = new Handler($this->createMock(Application::class));
    $class    = new \ReflectionClass(Handler::class);
    $method   = $class->getMethod('render');
    $method->setAccessible(true);
    $expectedInstance = Response::class;
    $this->assertInstanceOf($expectedInstance, $method->invokeArgs($instance, [$request, $this->createMock(Exception::class)]));
}
2
  • 1
    Any reason you don't call the route that will throw the exception directly? Commented Oct 27, 2017 at 10:11
  • 1
    Yes and no, this is Unit Test, and not Feature Test. Commented Oct 27, 2017 at 12:15

2 Answers 2

3

This how i do it :

/**
 * @test
 */
public function renderTokenMismatch()
{
    $request = $this->createMock(Request::class);
    $instance = new Handler($this->createMock(Container::class));
    $class    = new \ReflectionClass(Handler::class);
    $method   = $class->getMethod('render');
    $method->setAccessible(true);
    $expectedInstance = RedirectResponse::class;
    $this->assertInstanceOf($expectedInstance, $method->invokeArgs($instance, [$request, $this->createMock(TokenMismatchException::class)]));
}
Sign up to request clarification or add additional context in comments.

2 Comments

Error : Call to undefined method Mock_Request_e1709ead::wantsJson()
the answer above does: * instantiate Handler with mocked Container; * make render accessible via reflection; * call method on the handler instance, using mocked request and exception. if you're running into issues with undefined methods you can use a partial mock or mock the expected methods. also: extend the base Laravel TestCase if you're using translations
0

It's not easier do something like

$request = $this->createMock(Request::class);
$handler = new Handler($this->createMock(Container::class));
$this->assertInstanceOf(
     RedirectResponse::class,
     $handler->render(
           $request,
           $this->createMock(TokenMismatchException::class)
       )
    );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.