robmcvey
robmcvey

Reputation: 815

How to test CakeEmail is called from a model

In CakePHP 2.1 I'm trying to test that the CakeEmail::to() method is called from my model test case with the correct "to" email (In this example: [email protected]).

I want the following test to pass but I get:

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

Here's the code in the Model and the test case:

<?php

// Model/Job.php

App::uses('AppModel', 'Model');
App::uses('CakeEmail', 'Network/Email');

class Job extends AppModel {

        public function emailCat() {
                $CakeEmail = new CakeEmail();
                $CakeEmail->to('[email protected]');
                $CakeEmail->subject('hello!');
                $CakeEmail->emailFormat('text');
                $CakeEmail->config('default');
                $CakeEmail->send('hi');
        }

}

// Test/Model/JobTest.php

class JobTestCase extends CakeTestCase {

        public function setUp() {
                parent::setUp();
                $this->Job = ClassRegistry::init('Job');
        }      

        public function testEmailCat() {

                // I want to assert CakeEmail::to() is called with correct email
                $CakeEmail = $this->getMock('CakeEmail' , array('to'));
                $CakeEmail->expects($this->once())
                    ->method('to')
                    ->with($this->equalTo('[email protected]'));            

                $result = $this->Job->emailCat();
        }

}

Upvotes: 1

Views: 1195

Answers (1)

jeremyharris
jeremyharris

Reputation: 7882

The problem is that you're mocking a completely different class then the one that is actually used on the model. On your model function, you instantiate a brand new email class which will be mocked. Instead, you need to make sure that the CakeEmail object that the model uses is the one mocked.

class Job extends AppModel {

        public $CakeEmail = null;  

        public function emailCat() {
                if (!$CakeEmail) {
                        $this->CakeEmail = new CakeEmail();
                }
                $this->CakeEmail = new CakeEmail();
                $this->CakeEmail->to('[email protected]');
                $this->CakeEmail->subject('hello!');
                $this->CakeEmail->emailFormat('text');
                $this->CakeEmail->config('default');
                $this->CakeEmail->send('hi');
        }

}

Then update your test case to set the mock object on your Job model.

class JobTestCase extends CakeTestCase {

        public function setUp() {
                parent::setUp();
                $this->Job = ClassRegistry::init('Job');
        }      

        public function testEmailCat() {

                // I want to assert CakeEmail::to() is called with correct email
                $CakeEmail = $this->getMock('CakeEmail' , array('to'));
                $CakeEmail->expects($this->once())
                    ->method('to')
                    ->with($this->equalTo('[email protected]'));  
                // use mock object instead of creating a brand new one          
                $this->Job->CakeEmail = $CakeEmail;
                $result = $this->Job->emailCat();
        }

}

Upvotes: 3

Related Questions