0

I'm writing a test for a class that creates a new version of itself and inserts it into the database. The insert method returns an id which I want to record against the original class a bit like this.

class Invoice {

    public function creditInvoice() {
        $credit = new static();
        // ....
        $creditId = $credit->insert();
        $this->credited_by = $creditId;
        $this->update();
        return $credit;
    }

}

My test mocks the Invoice class and replaces update and insert. It then replaces insert with a function to return an id.

class InvoiceTest {

    public function testCreditInvoice {
        $invoice = $this->getMock('Invoice', array('update', 'insert'));
        $invoice->expects($this->any())
                ->method('insert')
                ->will($this->returnValue(1234));

        $credit = $invoice->creditInvoice();
        $this->assertTrue(
            $invoice->credited_by == 1234
        );
    }

}

This fails. It seems that although the new static() correctly makes a new version of the mock class, it doesn't bring the overridden method with it, so credited_by is actually null.

The only suggestion I've seen that would solve this is to create a new test class, that inherits Invoice but overrides the insert function to return my test data but this doesn't seem like good practice to me.

Is there a better way?

DanielM
  • 6,380
  • 2
  • 38
  • 57
  • I can change the code that's being tested if people think `new static()` is bad practice. – DanielM Jul 14 '14 at 11:13
  • I solved the problem by using dependency injection, however passing an object another instantiation of it's own class, which also needs to be blank, doesn't really seem like good coding practice to me (perhaps I'm wrong). If anyone has a solution which doesn't involve changing the context of the problem, it'd still be great to hear it. – DanielM Jul 14 '14 at 16:04

1 Answers1

0

new static is returning a new MockInvoice which doesn't have any expectations associated with it. This is why your test doesn't work. The new object is just a bare Mock object.

I am a little confused as to why you are creating a new instance of the class to just call the insert method. Why not just call $this->insert()? Then you don't have to worry about new static() at all.

IMO, it is not a good practice to have to create a mock of the class that you are testing. It seems that you are adding data to the database and I would have the insert and update as methods of a separate class. But your example code is a little sparse to get a complete idea of what it is that you are trying to accomplish.

Schleis
  • 41,516
  • 7
  • 68
  • 87
  • Sorry if it isn't very well explained. The `...` is just a place holder for "stuff happens here". It's an object that represents and Invoice, and I want to create a Credit against that Invoice. In this case a Credit is an Invoice of type Credit, same object, so I create it and use the Invoice data to create the credit. The `new static()` is for that, not the test. I always use `static` rather than `self` in case you inherit that class later. – DanielM Jul 15 '14 at 14:11