Ray
Ray

Reputation: 3060

phpunit test function in interface

Still learning how to test php

I now have a working interface (I think) - one of the functions is intended to create a series of records which I now want to test that is does. I admit I know very little about testing and so have more questions than knowledge.

So

My interface currently looks like this:

interface TicketCreatorInterface {

public function createTicket($input, $book);

}

My 'repository' class looks like this:

Class TicketCreator implements TicketCreatorInterface {

protected $ticket;

public function __construct(TicketAudit $ticketAudit)
{
    $this->ticket = $ticketAudit;
}

public function createTicket($input, $book) {

    $counter = $input['start'];

    while($counter <= $input['end']) {

        $this->$ticket->create(array(
            'ticketnumber'=>$counter,
            'status'=>'unused',
            'active'=>1
            ));

        $this->ticket->book()->associate($book);

        $counter = $counter+1;

    }

    return $counter;



}

And my attempts at a test looks like this:

public function testCreateCreatesTickets(TicketCreatorInterface $ticketCreator) {

    //arrange
    $book = Mockery::mock('Book');


    //act
    $response = $ticketCreator->createTicket(array('start'=>1000, 'end'=>1001), $book);

    // Assert...
    $this->assertEquals(true, $response);
 }

I tried first without typehinting the interface as without that I got an error of no object. I tried creating an instance on the interface but you can't do that so resorted to typehinting in the function

The error I get when I run the test is:

Argument 1 passed to TicketCreatorTest::testCreateCreatesTickets() must implement interface TicketCreatorInterface, none given

Creating interfaces is a new approach to me so don't yet understand all about it.

So how can I test this function does create a ticket as expected?

I've tested models with sqlite in memory database

Upvotes: 1

Views: 2759

Answers (1)

Schleis
Schleis

Reputation: 43790

You need to create an instance of the your TicketCreator in your test to call the method on. Change your test to this:

public function testCreateCreatesTickets() {

    //arrange
    $book = Mockery::mock('Book');
    $ticketAudit = Mockery::mock('TicketAudit');
    $ticketCreator = new TicketCreator($ticketAudit);


    //act
    $response = $ticketCreator->createTicket(array('start'=>1000, 'end'=>1001), $book);

    // Assert...
    $this->assertEquals(true, $response);
 }

Since you require a TicketAudit in your constructor, you will need to create a mock of that object also and pass it in to your constructor.

The only times that PHPUnit provides arguments to a test case is when you have a Data Provider or the tests depends on another test.

http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers

http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.examples.StackTest2.php

Keep in mind that you don't create an instance of an interface. If I want to make sure your object implements an interface, I will create a test that checks that the object is an instance of the interface using assertInstanceOf.

Upvotes: 6

Related Questions