Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test Laravel 5 controllers methods

We have Laravel 5 controllers method:

public function getInput()
{
    $input = \Request::all();
    $links = $input['links'];
    $this->startLinks =  explode("\n", $links);
    return $this;
}

How can we test this single method? How to pass POST request with data to this method? And how to create instance of this controller class in my test method?

like image 233
errogaht Avatar asked Apr 21 '15 19:04

errogaht


People also ask

What is PHPUnit testing?

PHPUnit is a unit testing framework for the PHP programming language. It is an instance of the xUnit architecture for unit testing frameworks that originated with SUnit and became popular with JUnit. PHPUnit was created by Sebastian Bergmann and its development is hosted on GitHub.

What is PHPUnit Laravel?

Use Laravel Unit Testing to Avoid Project-Wrecking Mistakes. Pardeep Kumar. 7 Min Read. PHPUnit is one of the most well known and highly optimized unit testing packages of PHP. It is a top choice of many developers for rectifying different developmental loopholes of the application.


2 Answers

This looks like a method which probably shouldn't belong in a controller. If you are serious about testing, I'd highly recommend reading up on the repository pattern. When testing, it will make your life a lot easier to have everything abstracted out of the controllers.=

With that said though, this is still very testable. The main idea is to figure out what needs to be tested and ONLY test that. This means we don't care what the dependencies are doing, only that they are doing and returning something which the rest of the method will need. In this case, it's the Request facade.

Then you want to make sure the variables are set appropriately and that the method returned an instance of that class. It actually ends up being pretty straight forward.

Should look something like this...

public function testGetInput()
{
    $requestParams = [
        'links' => "somelink.com\nsomeotherlink.com\nandanotherlink.com\ndoesntmatter.com"
    ];

    // Here we are saying the \Request facade should expect the all method to be called and that all method should
    // return some pre-defined things which we will use in our asserts.
    \Request::shouldReceive('all')->once()->andReturn($requestParams);

    // Here we are just using Laravel's IoC container to instantiate your controller.  Change YourController to whatever
    // your controller is named
    $class = App::make('YourController');

    // Getting results of function so we can test that it has some properties which were supposed to have been set.
    $return = $class->getInput();

    // Again change this to the actual name of your controller.
    $this->assertInstanceOf('YourController', $return);

    // Now test all the things.
    $this->assertTrue(isset($return->startLinks));
    $this->assertTrue(is_array($return->startLinks));
    $this->assertTrue(in_array('somelink.com', $return->startLInks));
    $this->assertTrue(in_array('nsomeotherlink.com', $return->startLInks));
    $this->assertTrue(in_array('nandanotherlink.com', $return->startLInks));
    $this->assertTrue(in_array('ndoesntmatter.com', $return->startLInks));
}
like image 191
user1669496 Avatar answered Sep 30 '22 12:09

user1669496


I think you are looking for this.

If your test class extends TestCase you will get a lot of helper methods which will do heavy lifting for you.

function testSomething() {
    // POST request to your controller@action
    $response = $this->action('POST', 'YourController@yourAction', ['links' => 'link1 \n link2']);
    // you can check if response was ok
    $this->assertTrue($response->isOk(), "Custom message if something went wrong");
    // or if view received variable
    $this->assertViewHas('links', ['link1', 'link2']);
}

Codeception extends this functionality even further.

like image 41
Daniel Antos Avatar answered Sep 30 '22 14:09

Daniel Antos