sica07
sica07

Reputation: 4956

PHPUnit mocked method called 0 times while it should be called once

I'm new to unit-testing and I'm having problems understanding the mocking object in phpunit. I have the following function:

public function createPaymentStatement()
{
    $tModel = new \FspInvoice\Model\Transaction();
    $paymentsArr = $this->transactionGateway->getTransactionWithStatus($tModel::SETTLED);
    $result = false;
    if(is_array($paymentsArr)){
            //some code here
            $result = $psArr;

    }

    return $result;
}

And now the uni-test for the function above:

 public function testCreatePaymentStatementWithPaymentsSettledReturnsArray()
{
    $this->transactionGateway = $this->getMockBuilder('FspInvoice\Model\TransactionsTable')
        ->setMethods(array('getTransactionWithStatus'))
        ->disableOriginalConstructor()
        ->getMock();
    $this->transactionGateway->expects($this->once())
        ->method('getTransactionWithStatus')
        ->will($this->returnValue(array(0,1,2)));
    $test = $this->service->createPaymentStatement();
    $this->assertTrue(is_array($test));
}

But when I run the code I get the error:

   1)FspInvoiceTest\ServiceTest\PaymentTest::testCreatePaymentStatementWithPaymentsSettledReturnsArray
Expectation failed for method name is equal to <string:getTransactionWithStatus> when    invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.

What am I doing wrong?

Upvotes: 3

Views: 3478

Answers (1)

Cyprian
Cyprian

Reputation: 11364

Your mock was never passed to the object you are testing. The thing you should remember is you don't mock a class, you mock an object of a class. So, you've created a mock, and then you have to pass it to your tested object somehow. In most cases you do it by depenedency injection.

In your original class inject dependency (through constructor for instance):

class TestedClass
{
    public function __construct(TransactionGateway $transactionGateway)
    {
        $this->transactionGateway = $transactionGateway;
    }

    public function createPaymentStatement()
    {
        // (...)
    }
}

And then in your test:

// create a mock as you did
$transactionGatewayMock = (...)

// pass the mock into tested object
$service = new TestedClass($transactionGateway);

// run test
$this->assertSomething($service->createPaymentStatement());

Upvotes: 10

Related Questions