how to test the protected method in zend - unit-testing

I want to test a model in zend project,
<?php
//require_once('CustomModelBase.php');
class Application_Model_User extends Custom_Model_Base {
protected function __construct() {
parent::__construct();
}
static function create(array $data) {
}
static function load($id) {
}
static function find($name, $order=null, $limit=null, $offset=null) {
);
}
}
the model in under application/model folder, it extends a base class Custom_Model_Base which is under the same folder as class User.
In my test, I try to create a new object of User in this way
<?php
class Model_UserTest extends ControllerTestCase
{
protected $user2;
public function setUp() {
parent::setUp();
$this->user2 = new Application_Model_User2();
}
public function testCanDoTest() {
$this->assertTrue(true);
}
}
this is CustomModelBase.php:
abstract class Custom_Model_Base
{
protected function __construct($adapter=null) {}
}
it gives me error, say "PHP Fatal error: Class 'Custom_Model_Base' not found in \application\models\User.php on line 4", the I include "CustomModelBase.php" in User.php,it gives me another error "PHP Fatal error: Call to protected Application_Model_User::__construct() from context 'Model_User2Test' in D:\PHP\apache2\htdocs\ID24_Xiao\tests\application\models \UserTest.php on line 13"
then How could I handle it? can anyone give some suggestion?

If you use 5.3.2 or better you could do it this way:
public function testCanDoTest() {
// set method "nameOfProctedMethod" to accessible on Class App...
$method = new ReflectionMethod(
'Application_Model_User2', 'nameOfProtectedMethod'
);
$method->setAccessible(true);
$this->assertTrue($method->doSomething());
}

You can not call any protected member of class from outside the class.
Either change the access modifier from protected to public
Or create a static function which will give the instance of that class, for e.g.
static function getInstance(){
return new Model_UserTest();
}

As Jeff has said, you can make your constructor testable by making it public like this:
public function __construct() { ...

Related

How to stub a public setter method for a protected property in Mockery

I want to stub a public setter method (setA()) for a protected property in the same class I am testing, but I am getting this error:
Cannot access protected property Mockery_2_Foo::$a
My goal is just to unit-test method1, but that method is calling setA, so I am not sure how I can stab out setA so it won't in any way interfere with the unit-test result for method1.
class Foo {
protected $a;
public function setA($val) {
$this->a = $val * 2;
}
public function method1($val) {
$this->setA($val);
return $val * 4;
}
............
}
/**
* #coversDefaultClass Foo
*/
class FooTest {
public function setUp(): void {
$this->foo = Mockery::mock(Foo::class)
->shouldAllowMockingProtectedMethods()
->makePartial();
}
/**
* #covers ::method1
*/
public function testMethod1() {
$this->foo->shouldReceive('setA')
->set('a', 4);
$this->assertEquals(8, $this->foo->method1(2));
}
..........
}``
Mockery can only set public properties (see docs).
I don't really get what you are trying to do, but maybe it's just because of your simplified example. Instead of using Mockery you could just create an anonymous class that extends Foo and adds the desired behavior:
class FooTest extends TestCase
{
public function testMethod1()
{
$foo = new class extends Foo {
public function setA($val)
{
$this->a = 4;
}
};
self::assertEquals(8, $foo->method1(2));
}
}

Laravel 5.2 Unit Testing Repository with Mocking "does not have method"

In Laravel 5.2, I want to unit test my Eloquent User Repository.
class EloquentUserRepository implements UserRepositoryInterface
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function oneUser($id)
{
return $this->user->oneUser($id);
}
}
My test looks like below, with mocking the interface:
class EloquentUserRepositoryTest extends TestCase
{
public function setUp()
{
$this->user = factory(User::class, 1)->create(['name' => 'foo']);
}
/** #test */
public function it_fetch_an_user()
{
$mock = Mockery::mock('App\Repositories\Interfaces\UserRepositoryInterface')
->shouldReceive('oneUser')
->once()
->with($this->user->id)
->andReturn('foo');
App::instance(App\Repositories\EloquentUserRepository::class, $mock);
$userRepository = App::make(App\Repositories\EloquentUserRepository::class);
$this->assertEquals('foo', $userRepository->oneUser($this->user->id)->name);
}
public function tearDown()
{
Mockery::close();
}
}
I get this error:
ErrorException: call_user_func_array() expects parameter 1 to be a valid callback, class 'Mockery\Expectation' does not have a method 'oneUser'
I expect a simulated object that has the method oneUser, but it returns Mockery\Expectation. What do I wrong?
When a new instance of EloquentUserRepository is made, a new user model is created. When you then call the oneUser method for the EloquentUserRepository class a method with the same name is called but on the user model. Therefore it's the user model you need to mock, not the UserRepositoryInterface.
You need to create a new instance of the EloquentUserRepository and send in the user model mock as an argument when it's created as shown below:
class EloquentUserRepositoryTest extends TestCase
{
protected $userMock;
public function setUp()
{
parent::setUp();
$this->userMock = Mockery::mock('User');
$this->userMock->id = 1;
}
/** #test */
public function it_fetch_an_user()
{
$this->userMock->shouldReceive('oneUser')->with($this->userMock->id)->andReturn('foo');
$userRepository = App::make(App\Repositories\EloquentUserRepository::class, array($this->userMock));
$this->assertEquals('foo', $userRepository->oneUser($this->userMock->id));
}
public function tearDown()
{
Mockery::close();
}
}

Invalid setup on a non-overridable member:

I'm trying to test the function GetcallEntityBycallEntity (Guid callId) with Mock library.
this function calls another class that does not implement any interface.
protected virtual CallFacade CallFacade()
{
return new CallFacade();
}
public Note GetCallEntityByCallEntity(Guid CallEntity)
{
myCall= null;
**CallFacade** callFacade = Get CallFacade();
if (CallEntity!= Guid.Empty)
{
myCall = callFacade.GetCallByEntityId(CallEntity);
}
return myCall;
}
CallFacade Not is an Interface
in my test:
[TestInitialize]
public void TestInitialization()
{
IoCMocks.Initialize();
CommonCallFacadeMock = new CommonCallFacadeMock();
}
public void GetCallEntityByNoteEntity_GetCall_ReturnValidCall()
{
//Arrange
CallmyNote = GetmyCall(); //private method. == Call.CreateCall();
//Stubs
CommonCallFacadeMock.MockCallFacade.Setup(x => x.GetCallByEntityId(ExistingCallEntity)).Returns(myCall);
//Action
var obtained = CommonCallFacadeMock.GetCallEntityByCallEntity(ExistingCallEntity);
CommonCallFacadeMock.MockCallFacade.Verify(x => x.GetCallByEntityId(It.IsAny<Guid>()), Times.Once());
}
You get this error message because MOQ can mock only interfaces, abstract methods or properties on abstract classes, virtual methods or properties on concrete classes.
You have to mark method GetCallByEntityId as virtual.
There is an old discussion in "Moq Discussions" google group about virtual methods.

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;
}
}
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*/));
}
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());
}

Using inheritance in MSTest

I am setting up some MSTest based unit tests. To make my life easier I want to use a base class that handles the generic setup and taredown all of my tests require. My base class looks like this:
[TestClass]
public class DBTestBase {
public TestContext TestContext { get; set; }
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext) {
var config = new XmlConfigurationSource("ARconfig_test.xml");
ActiveRecordStarter.Initialize(Assembly.Load("LocalModels"), config);
}
[TestInitialize()]
public void MyTestInitialize() {
ActiveRecordStarter.CreateSchema();
Before_each_test();
}
protected virtual void Before_each_test() { }
[TestCleanup()]
public void MyTestCleanup() {
After_each_test();
}
protected virtual void After_each_test() { }
}
My actual test class looks like this:
[TestClass]
public class question_tests : DBTestBase {
private void CreateInitialData() {
var question = new Question()
{
Name = "Test Question",
Description = "This is a simple test question"
};
question.Create();
}
protected override void Before_each_test() {
base.Before_each_test();
CreateInitialData();
}
[TestMethod]
public void test_fetching() {
var q = Question.FindAll();
Assert.AreEqual("Test Question", q[0].Name, "Incorrect name.");
}
}
The TestInitialize function works as expected. But the ClassInitialize function never runs. It does run if I add the following to my child class:
[ClassInitialize()]
public static void t(TestContext testContext) {
MyClassInitialize(testContext);
}
Is it possible to get my base class initialize function to run without referencing it in my child class?
ClassInitialize method is executed if and only if the concerned "class" contains at least one TestMethod, and at least one TestMethod from the class is selected for execution.
Confirm this was a problem for me too. I used a constructor on the base and a destructor for the cleanup
[TestClass]
public class question_tests : DBTestBase {
...
[TestCleanup()]
public void TestCleanup()
{
base.MyTestCleanup();
}