具有多种方法的Mockery Doctrine / Repository

时间:2015-12-02 20:13:59

标签: doctrine-orm phpunit mockery

我正在使用mockery来测试一个方法,该方法使用不同的存储库进行大量的doctrine存储库调用。 这是我设置所有存储库模拟的方法:

public function testService()
{
    $mockDoctrine = $this->getMockDoctrine();
    $mockDoctrine->shouldReceive('getRepository')->once()
        ->andReturn($this->getRepositoryAMock());

    $mockDoctrine->shouldReceive('getRepository')->once()
        ->andReturn($this->getRepositoryBMock());

    $mockDoctrine->shouldReceive('getRepository')->once()
        ->andReturn($this->getRepositoryCMock());

    //here is where i hit my test
    $products = $this->service->fire(1, 1);

    $this->assertInstanceOf('Illuminate\Support\Collection', $products);
    foreach ($products as $v) {
        $this->assertInstanceOf('Illuminate\Support\Collection', $v);
    }
}

这是我嘲笑学说的方法:

public function getMockDoctrine()
{
    $mockDoctrine = \App::make('Doctrine');
    $mockDoctrine->shouldReceive('persist')
        ->andReturn(true);
    $mockDoctrine->shouldReceive('flush')
        ->andReturn(true);

    return $mockDoctrine;
}

这些是我的存储库mock

public function getRepositoryAMock()
{
    $repository = \Mockery::mock('MyARepository');
    $repository->shouldReceive('findBy')
        ->with(['paramA' => 1, 'paramB' => 1])
        ->andReturn($this->getMockA());

    return $repository;
}

public function getRepositoryBMock()
{
    $repository = \Mockery::mock('MyBRepository');
    $repository->shouldReceive('findById')
        ->with(1)
        ->andReturn($this->getMockA());

    return $repository;
}

public function getRepositoryCMock()
{
    $repository = \Mockery::mock('MyCRepository');
    $repository->shouldReceive('findOneBy')
        ->with(['paramA' => 1, 'paramB' => 1])
        ->andReturn($this->getMockA());

    return $repository;
}

这实际上我设置了模拟

的返回
public function getMockA()
{
    $obj = new MyClass();
    $reflection = new \ReflectionClass($obj);
    $id = $reflection->getProperty('id');
    $id->setAccessible(true);
    $id->setValue($obj, 1);
    $obj
        ->setLogin('foo')
        ->setPassword('bar')
        ->setCode(1);

    return $obj;
}

然后我收到这样的错误:

1)MyClassTest :: testService BadMethodCallException:方法Mockery_2_ClassBRepository :: findOneBy()在此模拟对象上不存在

假设我有3个方法在testService()方法中调用了存储库,那么mockery没有找到的方法是在第三个,但是mockery认为它在第二个,所以很明显他不会找到,因为在第二个,不存在" findOneBy()"教条方法就在第三个方面。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

你应该可以使用()嘲讽 例如:

$mockDoctrine
    ->shouldReceive('getRepository')
    ->with('MyAReposiotry')->once()
    ->andReturn($this->getRepositoryAMock());

和每个存储库(具有不同的值)一样。

但我宁愿在该服务中注入存储库,而不是从服务中的实体管理器获取存储库。它更适合测试。看看this blog post

答案 1 :(得分:0)

感谢伊万先生,

现在我的方法正在运作。

在我的真课中,我正在使用实体类获取存储库 像:

 Doctrine::getRepository('MyEntityClassA')
        ->findBy(['paramA' => 1, 'paramB' => 1]);

所以我改变了我的测试方法,使用“with”传递实体类:

public function testService()
{
    $mockDoctrine = $this->getMockDoctrine();
    $mockDoctrine->shouldReceive('getRepository')
        ->with('MyEntityClassA')->once()
        ->andReturn($this->getRepositoryAMock());

    $mockDoctrine->shouldReceive('getRepository')->once()
        ->with('MyEntityClassB')->once()
        ->andReturn($this->getRepositoryBMock());

    $mockDoctrine->shouldReceive('getRepository')->once()
        ->with('MyEntityClassC')->once()
        ->andReturn($this->getRepositoryCMock());

    //here is where i hit my test
    $products = $this->service->fire(1, 1);

    $this->assertInstanceOf('Illuminate\Support\Collection', $products);
    foreach ($products as $v) {
        $this->assertInstanceOf('Illuminate\Support\Collection', $v);
    }
}