dongxiangchan0743 2017-01-18 01:43
浏览 92

PHPUnit将mock对象作为参数传递给另一个对象的构造函数,并使用expected()方法

I'm trying to assert that a method on an object (object under test) is called at least once during the construction of another object. I want to use phpunit's expects() functionality to test that a getDetails() method is called. This function is called during the construction of another customer account object. I must be missing something fundamental about the way phpunit works but I may be approaching the problem with a python mindset. I know I could get this working in python but perhaps it's not possible here? Here is my test code:

public function testPhoneBookCode()
{
    $account = 'testaccount';

    $phone_book_mock = $this->getMockBuilder('\corp\data\PhoneBook')
        ->setConstructorArgs(array(null))
        ->setMethods(null)
        ->getMock();

    $expected = array(
        'id' => 1234,
        'title' => 'Mr',
        'first_name' => 'George',
        'last_name' => 'Smith',
        'phone' => '111-111-1111'
    );

    $phone_book_mock->expects($this->atLeastOnce())
        ->method('getDetails')
        ->with($this->equalTo(1234))
        ->will($this->returnValue($expected));

    try {
        $c = new Customer_Account(
            $account,
            true,
            'acme_corp',
            1234,
            null,
            null,
            $phone_book_mock
        );

    } catch ( \Exception $e ) {
        $this->fail("An unexpected exception has been raised [$account].". $e);
    }
}

At this point I would expect the instantiation of the Customer_Account class to call the getDetails method on my mock and the atLeastOnce check to return true.

This code is modified from a real life example. So any typos may have been introduced when re-typing. In the real life code the 'phone_book' is passed into the Customer_Account object's constructor and the getDetails() method is called in that constructor. I have confirmed that the method IS actually being called and I'm getting the return value I expect. However my mock expects() test is failing.

Expectation failed for method name is equal to when invoked at least once. Expected invocation at least once but it never occured.

The mock is not registering the call to getDetails() even though I'm confident the right code is being called. Is what I'm trying to do just not possible? Do I lose the reference to the mock object once I pass it to another constructor? Is there another way to accomplish this? Any help would be greatly appreciated.

  • 写回答

1条回答 默认 最新

  • dongling3243 2017-08-28 20:18
    关注

    This should work to assert that PhoneBook::details() is invoked with $id when you create an instance of Customer_Account:

    public function testPhoneBookCode()
    {
        $id = 1234;
    
        $details = [
            'id' => $id,
            'title' => 'Mr',
            'first_name' => 'George',
            'last_name' => 'Smith',
            'phone' => '111-111-1111'
        ];
    
        $phoneBook = $this->createMock('corp\data\PhoneBook');
    
        $phoneBook
            ->expects($this->atLeastOnce())
            ->method('getDetails')
            ->with($this->identicalTo($id))
            ->willReturn($details);
    
        new Customer_Account(
            'testaccount',
            true,
            'acme_corp',
            $id,
            null,
            null,
            $phoneBook
        );
    }
    

    For reference, see:

    评论

报告相同问题?

悬赏问题

  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序
  • ¥15 onvif+openssl,vs2022编译openssl64
  • ¥15 iOS 自定义输入法-第三方输入法
  • ¥15 很想要一个很好的答案或提示
  • ¥15 扫描项目中发现AndroidOS.Agent、Android/SmsThief.LI!tr
  • ¥15 怀疑手机被监控,请问怎么解决和防止
  • ¥15 Qt下使用tcp获取数据的详细操作
  • ¥15 idea右下角设置编码是灰色的
  • ¥15 全志H618ROM新增分区
  • ¥15 在grasshopper里DrawViewportWires更改预览后,禁用电池仍然显示