Crazylife's avatar

How to write a test case for generate PDF?

How do i test if i passed correct data to generate PDF?

$data = Model::where('id', 1)->first();
 $date = Carbon::parse($data->created_at)->format('d/m/Y');
 $pdf = PDF::loadView('printPDF', compact('data', 'date'));

return $pdf->download($data->runningNumber . '.pdf');

This is the sample of my controller. How can i create a test case for this? I want to check the $data passed to the view to generate the PDF.

0 likes
6 replies
shamtoro's avatar

You'll probably want to have some sort of validation logic to test if the data passed to the PDF is correct. If it isn't correct, you'll want to throw an exception.

In your test, you will then test both paths.

The happy path-- pass in a correct model instance, and assert that no exception was found.

The not so happy path-- pass in an incorrect model / data, and assert that an exception was thrown.

As far as the PDF creation goes, you can mock its creation using Laravel's built in Mockery implementation.

Since Laravel's testing classes use PHPUnit under the hood, you can test exceptions with this format: https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html?highlight=exception#testing-exceptions

As for mocking your PDF generating logic, take a look at this: https://laravel.com/docs/8.x/mocking#mocking-objects

1 like
laracoft's avatar

@crazylife

It is better to break the test up into at least 2 parts.

  1. Testing your data is valid
  2. Testing that PDF generates data that it was given

#1 is very contextual, I suppose you know how to test for that.

#2 involves passing known data to the PDF generator and using a PDF parser (e.g. https://github.com/smalot/pdfparser ) to check that the generator produced the correct data

1 like
Crazylife's avatar

I am doing it in this way

 public function test_can_generate_pdf()
    {
        PDF::shouldReceive('loadView')
             ->once()
             ->andReturnSelf()
             ->getMock()
             ->shouldReceive('download')
             ->once()
             ->with('welcome.pdf')
             ->andReturn('THE_PDF_BINARY_DATA');

        $this->get('/download')
             ->assertSuccessful()
             ->assertSeeText('THE_PDF_BINARY_DATA');
    }

Sorry i am still new to test stuff, i stucked when i am going to check with the data pass into the loadView to generate PDF.

In my controller,

public function generatePDF(Model $model) {}

Basically i just throw $model to the view to generate PDF. How can i test on the data needed for the pdf? Not sure how i am going to test on this.

laracoft's avatar

Can your test run? which line is failing?

Let me try and rephrase it, the way you are writing your current test is too "big".

Your PDF test should be something like below:

  1. Pass "ABC" to PDF generator
  2. Generate PDF
  3. Check (assertSeeText) that the PDF contains "ABC"

If this test passes, means you have no issues about generating PDFs. Then it really does not matter whether you are choosing to write "DEF" or "XYZ" to your PDF, it is safe to assume it will write correctly.

However, if your question is about how to perform step 3, i.e. assertSeeText that PDF contains "ABC" Could you please explain which PDF facade you are using?

1 like
Crazylife's avatar

Yes, it works fine for my previous test on generate PDF.

I am using DOMPDF

Oh, what i mean is to check the value passed into pdf e.g. I am populating my PDF with the value $model->name, $model->created_at.

Do i really need a test on this and how can the test be done actually?

laracoft's avatar

@crazylife

As I tried to explain twice earlier, no, you don't need to test if you can see $model->name and created_at.

Think of it like this, if you are trying to test if a computer can add, do you ask it to add every possible known number? You give it 2 numbers, if it returns the correct result, we assume it can perform addition correctly.

So the 2 tests to perform is,

  1. Can the code generate a PDF containing with the example data provided?
  2. Does the code have the correct ->name and ->created_at

What you are trying to do now is to ask the 2 questions together and it is too complicated.

  1. Does the generated PDF have the correct ->name and ->created_at

Please or to participate in this conversation.