Skip to content

2023-01-04 - Mocking repositories

You are viewing an outdated version of the documentation.
Click here to switch to the stable version (v6.6), or use the version switcher on the left to navigate between versions.

2023-01-04 - Mocking repositories

INFO

This document represents an architecture decision record (ADR) and has been mirrored from the ADR section in our Shopware 6 repository. You can find the original version here

Context

Right now it is complicated to test classes which has a dependency on a repository. This is because mocking a repository search or searchIds call requires creating empty EntitySearchResults or IdSearchResults. This leads to much boilerplate code when writing tests and faking database results. For this reason we should provide a way to mock the search and searchIds calls in a much easier way.

Faking a search results of a repository looks like this at the moment:

php
$result = new EntitySearchResult(
    'my-entity',
    1,
    new EntityCollection([]),
    null,
    new Criteria(),
    Context::createDefaultContext()
);

$entityRepository = $this->createMock(EntityRepository::class);
$entityRepository
    ->expects(static::once())
    ->method('search')
    ->willReturn($result);

Solution

We created a \Shopware\Tests\Unit\Common\Stubs\DataAbstractionLayer\StaticEntityRepository which allows the developer to easily fake repository search results.

How to use

php
<?php

class SomeCoreClass
{
    public function __construct(private EntityRepository $repository) {}
    
    public function foo() 
    {
        $criteria = new Criteria();
        
        $result = $this->repository->search($criteria, $context);
        
        // ...
    }
}

class SomeCoreClassTest extends TestCase
{
    public function testFoo() 
    {
        $repository = new StaticEntityRepository([
            new UnitCollection([
                new UnitEntity(),
                new UnitEntity(),
            ])
        ]);
        
        $class = new SomeCoreClass($repository);
        
        $class->foo();
        
        // some assertions
    }
}

The StaticEntityRepository constructor accepts an array of EntitySearchResults, EntityCollections or AggregationResultCollection. The value is the result of the search or one of the supported collections.

Other configurations

php
<?php

class SomeCoreClassTest extends TestCase
{
    public function testFoo() 
    {
        $repository = new StaticEntityRepository([
            new UnitCollection([
                new UnitEntity(),
            ]),
            new AggregationResultCollection([
                new AvgResult('some-aggregation', 12.0),
            ]),
            new EntitySearchResult(
                'entity', 
                1, 
                new EntityCollection(), 
                new AggregationResultCollection(), 
                new Criteria(), 
                Context::createDefaultContext()
            ),
            [Uuid::randomHex(), Uuid::randomHex(), Uuid::randomHex()]       
            new IdSearchResult(0, [], new Criteria(), Context::createDefaultContext()),
        ]);
        
        $class = new SomeCoreClass($repository);
        
        $class->foo();
        
        // some assertions
    }
}