Consider class below:

class FillTestBySerialHandler

     * @var FillTestBySerialRepository
    private $fillTestBySerialRepository;

    function __construct(FillTestBySerialRepository $fillTestBySerialRepository)
        $this->fillTestBySerialRepository = $fillTestBySerialRepository;

    function handle(): ResponseInterface
        $serial = filter_var($_GET['serial'], FILTER_VALIDATE_INT);

        if (is_int($serial))
            $row = $this->fillTestBySerialRepository->getDataBySerial($serial);
            $row['error'] = 'Error: Invalid serial number.';

        return new JsonResponse($row);

This is a request handler, that receives a serial number, validates that it is an integer, and sends the $serial to repository layer, to get some data.

Data is returned in an array form, compiled into JSON and sent back to the caller.

This may be confusing, but my use case is for a Web "Test", where "Test" is the name for the business logic. Do not confuse the "Test" use case with unit test!

I want to write tests for this class. Which tests should be written if I want to tests the class and be sure that when the tests break, it is a real issue that needs to be looked into?

Here is what I am doing now - I wrote two tests.

I mocked up the FillTestBySerialRepository class with fake data and used it to test the FillTestBySerialHandler. This means that even if my real database fails or changes structure or data, my test will NOT fail and will still pass, because FillTestBySerialRepository is mocked up.

After I wrote that test I thought well, how will I know about the database breaking? So I wrote another test to test the FillTestBySerialRepository. Namely it's just comparing mocked up data to the one pulled from real life database at the time of test. So if that breaks, I will know that the database changed and is the cause of error.

But then I thought, if I am doing that in the first place, why am I mocking up the database data? Why not just rewrite the first test using real data without any mockups.

At this point I think I need advice on how to test my Handlers, and I am here. Please help! What types of tests are typically written for Handlers with repository layer? (Handler is in the same class as Controller/Action in PHP framework parlance).


You should be testing at multiple levels.

At the lowest level are unit tests that exercise a single unit of code in isolation (that could be a single Handler). The advantage of unit tests is that they are typically automated and should be designed to be fast so that they can be executed very often without interrupting you, the developer, in your workflow.

At an intermediate level, you can have integration tests, where you verify that multiple units of code work correctly together (after having verified in unit tests that they work correctly in isolation).

At the highest level, you have system tests, where you verify that the system as a whole works correctly.

You should try to test functionality at the lowest possible level, because that will give you more detailed information where the problem lies and those tests are typically easier to automate.
Especially databases and network connections are troublesome when testing. For one, they are slow. And next to that, databases tend to remember changes across tests, which may cause tests to depend on other tests, and networks can fail at the wrong time, causing tests to fail randomly. You should try to fake both of them in the bulk of your testing.

With that said, I would have these tests:

  • At unit level
    • Success scenario for the Handler
    • Several failure scenarios for the Handler (no serial, non-integer serial, integer but non-existing serial, really large integer serial)
    • Success scenario for the Repository
    • Failure scenario for the Repository (requesting non-existing serial)
  • At system or integration level
    • Single test that the Handler works correctly with the real repository

The higher-level test shows primarily that the expectations you have encoded in the fakes used in the unit tests are true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.