kaklon
kaklon

Reputation: 2432

how to create a mock in a model test case

Maybe I am doing this wrong.

I'd like to test the beforeSave method of a model (Antibody). A part of this method calls a method on an associated model (Species). I'd like to mock the Species model but don't find how.

Is it possible or am I doing something that goes against the MVC pattern and thus trying to do something that I shouldn't?

class Antibody extends AppModel {
    public function beforeSave() {

        // some processing ...

        // retreive species_id based on the input 
        $this->data['Antibody']['species_id'] 
            = isset($this->data['Species']['name']) 
            ? $this->Species->getIdByName($this->data['Species']['name']) 
            : null;

        return true;
    }
}

Upvotes: 5

Views: 3140

Answers (2)

dr Hannibal Lecter
dr Hannibal Lecter

Reputation: 6721

Assuming your Species model in created by cake due to relations, you can simply do something like this:

public function setUp()
{
    parent::setUp();

    $this->Antibody = ClassRegistry::init('Antibody');
    $this->Antibody->Species = $this->getMock('Species');

    // now you can set your expectations here
    $this->Antibody->Species->expects($this->any())
        ->method('getIdByName')
        ->will($this->returnValue(/*your value here*/));
}

public function testBeforeFilter()
{
    // or here
    $this->Antibody->Species->expects($this->once())
        ->method('getIdByName')
        ->will($this->returnValue(/*your value here*/));
}

Upvotes: 6

Laurent Sarrazin
Laurent Sarrazin

Reputation: 774

Well, it depends on the way your 'Species' object is injected. Is it injected via the constructor ? Via a setter ? Is it inherited ?

Here is an example with a constructor injected object :

class Foo
{
    /** @var Bar */
    protected $bar;

    public function __construct($bar)
    {
        $this->bar = $bar;
    }

    public function foo() {

        if ($this->bar->isOk()) {
            return true;
        } else {
            return false;
        }
    }
}

Then your test would be something like this:

public function test_foo()
{
    $barStub = $this->getMock('Overblog\CommonBundle\TestUtils\Bar');
    $barStub->expects($this->once())
        ->method('isOk')
        ->will($this->returnValue(false));

    $foo = new Foo($barStub);
    $this->assertFalse($foo->foo());
}

The process is quite the same with setter injected objects :

public function test_foo()
{
    $barStub = $this->getMock('Overblog\CommonBundle\TestUtils\Bar');
    $barStub->expects($this->once())
        ->method('isOk')
        ->will($this->returnValue(false));

    $foo = new Foo();
    $foo->setBar($barStub);
    $this->assertFalse($foo->foo());
}

Upvotes: 0

Related Questions