使用 PHPUnit 模拟对象是否有可能期望调用神奇的 __call() 方法?

发布于 2024-11-13 09:22:51 字数 524 浏览 2 评论 0原文

我在测试中有一个模拟对象。真实的对象 PageRepository 使用 __call() 实现了一个神奇的方法,因此如果您调用 $pageRepository->findOneByXXXX($value_of_field_XXXX),它将在数据库中搜索与该参数匹配的记录。

有没有办法模拟该方法?

真正的方法调用看起来像这样:

$homepage = $pageRepository->findOneBySlug('homepage');

测试看起来像这样:

$mockPageRepository->expects($this->any())
    ->method('findOneBySlug')
    ->will($this->returnValue(new Page()));

但它不起作用——PHPUnit 没有发现方法调用。让它看到该方法的唯一方法是在 PageRepository 中显式定义该方法。

I've got a mock object in a test. The real object, PageRepository, implements a magic method using __call(), so if you call $pageRepository->findOneByXXXX($value_of_field_XXXX), it will search the database for records matching that parameter.

Is there a way to mock that method?

The real method call would look something like this:

$homepage = $pageRepository->findOneBySlug('homepage');

The test would look like this:

$mockPageRepository->expects($this->any())
    ->method('findOneBySlug')
    ->will($this->returnValue(new Page()));

But it doesn't work -- PHPUnit doesn't spot the method call. The only way to get it to see the method is to define the method explicitly in PageRepository.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

恰似旧人归 2024-11-20 09:22:51

PHPUnit 的 getMock() 采用第二个参数,一个包含要模拟的方法名称的数组。
如果在此数组中包含方法名称,则模拟对象将包含具有该名称的方法,expects() 和朋友将使用该方法。

这甚至适用于“真实”类中未定义的方法,因此类似以下内容应该可以解决问题:

$mockPageRepository = $this->getMock('PageRepository', array('findOneBySlug'));

请记住,您必须显式包含也需要模拟的任何其他方法,因为 数组中指定的方法是为模拟对象定义的。

PHPUnit's getMock() takes a second argument, an array with the names of methods to be mocked.
If you include a method name in this array, the mock object will contain a method with that name, which expects() and friends will work on.

This applies even for methods that are not defined in the "real" class, so something like the following should do the trick:

$mockPageRepository = $this->getMock('PageRepository', array('findOneBySlug'));

Keep in mind that you'll have to explicitly include any other methods that also need to be mocked, since only the methods named in the array are defined for the mock object.

尹雨沫 2024-11-20 09:22:51

我找到了更好的方法来做到这一点。仍然不完美,但您不必手动指定所有模拟类方法,只需指定魔术方法:

    $methods = get_class_methods(PageRepository::class);
    $methods[] = 'findOneBySlug';
    $pageRepositoryMock = $this->getMockBuilder(PageRepository::class)
        ->disableOriginalConstructor()
        ->disableOriginalClone()
        ->disableArgumentCloning()
        ->disallowMockingUnknownTypes()
        ->setMethods($methods)
        ->getMock();

I found better way to do this. Still not perfect, but you don't have to specify all mocking class methods by hand, only magic methods:

    $methods = get_class_methods(PageRepository::class);
    $methods[] = 'findOneBySlug';
    $pageRepositoryMock = $this->getMockBuilder(PageRepository::class)
        ->disableOriginalConstructor()
        ->disableOriginalClone()
        ->disableArgumentCloning()
        ->disallowMockingUnknownTypes()
        ->setMethods($methods)
        ->getMock();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文