Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate Accept header in a test within a Laravel 5 package?

Tags:

I'm currently building a Laravel package that injects a new method in Illuminate\Http\Request via Macros. The method I'm injecting has been completed and is expected to work nicely, but I also want to test it before releasing it.

My test requires me to change the request's Accept header, in order for me to see if the test is passing or no. So I have done the following to simulate the request:

// package/tests/TestCase.php  namespace Vendor\Package;  use Illuminate\Http\Request; use Orchestra\Testbench\TestCase as Orchestra;  abstract class TestCase extends Orchestra {     /**      * Holds the request      * @var Illuminate\Http\Request      */     protected $request;      /**      * Setup the test      */     public function setUp()     {         parent::setUp();          $this->request = Request::capture();          $this->request->headers->set('Accept', 'application/x-yaml');     } } 

Then in my test I use the method I'm injecting into Request with $this->request->wantsYaml() and it's always returning false since the Accept header is not getting set to application/x-yaml.

class RequestTest extends TestCase {     /** @test */     public function it_should_return_a_bool_if_page_wants_yaml_or_not()     {         dump($this->request->wantsYaml()); // Return false          $this->assertTrue($this->request->wantsYaml()); // It fails!     } } 

How do I go on simulating the headers in a test in Laravel package development?


EDIT

This is my YamlRequest class

use Illuminate\Http\Request; use Illuminate\Support\Str;  class YamlRequest extends Request {     /**      * Acceptable content type for YAML.      * @var array      */     protected $contentTypeData = ['/x-yaml', '+x-yaml'];      /**      * Determine if the current request is asking for YAML in return.      *      * @return bool      */     public function wantsYaml()     {         $acceptable = $this->getAcceptableContentTypes();          // If I dd($acceptable), it comes out as empty during tests!          return isset($acceptable[0]) && Str::contains($acceptable[0], $this->contentTypeData);     } } 

So I literally have to simulate the Accept in order to see if my wantsYaml method is working as expected.

like image 602
aborted Avatar asked Jun 30 '16 13:06

aborted


People also ask

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.

What is the most popular testing framework used with Laravel?

For developers, Laravel can be used with Angular JS for developing large single page web applications.


1 Answers

A partially mocked object would allow you to test your Illuminate\Http\Request::macro without also testing ancillary methods within Laravel's Illuminate\Http\Request object. In other words, all you really need to know is that your macro works. You don't need to test that a Request can be constructed and that its headers can be set.

In the following tests, I'll setup a "partially" mocked version of your YamlRequest object using Mockery.

Partial mocks are useful when we only need to mock several methods of an object leaving the remainder free to respond to calls normally (i.e. as implemented).

See the Mockery Documentation, Creating Partial Mocks.

The partial mock will allow us to mock the methods from Laravel's Request object while leaving your macro free to run as it would in a production environment.

use YamlRequest; use \Mockery;  class RequestTest extends TestCase {     public function setUp()     {         parent::setUp();          $this->request = Mockery::mock(YamlRequest::class)->makePartial();     }      public function test_that_wants_yaml_returns_true_given_x-yaml_accept_header()     {         /**          *  This line allows you to control the return value of          *  Illuminate\Http\Request::getAcceptableContentTypes while your macro          *  is running.          */         $this->request->allows(             [                 'getAcceptableContentTypes' => ['application/x-yaml', 'text/html']             ]         );          $this->assertTrue($this->request->wantsYaml());     }      public function test_that_wants_yaml_returns_false_given_json_accept_header()     {         $this->request->allows(             [                 'getAcceptableContentTypes' => ['application/json', 'text/html']             ]         );          $this->assertFalse($this->request->wantsYaml());     } } 
like image 132
Travis Hohl Avatar answered Oct 07 '22 14:10

Travis Hohl