Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test for mocking a method called by new class object

I am writing unit test for an existing code which is like this

class someClass {     public function __construct() { ... }      public function someFoo($var) {         ...         $var = "something";         ...         $model = new someClass();         model->someOtherFoo($var);     }      public someOtherFoo($var){          // some code which has to be mocked     } } 

Here how should I be able to mock the call to function "someOtherFoo" such that it doesn't execute "some code" inside someOtherFoo?

class someClassTest {    public function someFoo() {       $fixture = $this->getMock('someClass ', array('someOtherFoo'));       $var = "something";       ....       // How to mock the call to someOtherFoo() here    }  } 

Is it possible to mock out the constructor so that it returns my own constructed function or variable?

Thanks

like image 575
Sumitk Avatar asked Oct 13 '11 21:10

Sumitk


People also ask

How do you unit test classes which create new objects?

The first step is to import Mockito dependencies into your code. Now let us see an example of how to test the class. Let us assume the below is the class that we want to test. Below is the sample class of the object that is instantiated in ClassToBeTested.

How do you mock a test class method?

We can mock runInGround(String location) method inside the PersonTest class as shown below. Instead of using mock(class) here we need to use Mockito. spy() to mock the same class we are testing. Then we can mock the method we want as follows.

How do you mock an object in unit testing?

What is mocking? Mocking is a process used in unit testing when the unit being tested has external dependencies. The purpose of mocking is to isolate and focus on the code being tested and not on the behavior or state of external dependencies.

How do you know if mocked method called?

To check if a method was called on a mocked object you can use the Mockito. verify method: Mockito. verify(someMock).


1 Answers

Wherever you have new XXX(...) in a method under test, you are doomed. Extract the instantiation to a new method--createSomeClass(...)--of the same class. This allows you to create a partial mock of the class under test that returns a stubbed or mock value from the new method.

class someClass {     public function someFoo($var) {         $model = $this->createSomeClass();  // call method instead of using new         model->someOtherFoo($var);     }      public function createSomeClass() {  // now you can mock this method in the test         return new someClass();     }      public function someOtherFoo($var){          // some code which has to be mocked     } } 

In the test, mock createSomeClass() in the instance on which you call someFoo(), and mock someOtherFoo() in the instance that you return from the first mocked call.

function testSomeFoo() {     // mock someOtherFoo() to ensure it gets the correct value for $arg     $created = $this->getMock('someClass', array('someOtherFoo'));     $created->expects($this->once())             ->method('someOtherFoo')             ->with('foo');      // mock createSomeClass() to return the mock above     $creator = $this->getMock('someClass', array('createSomeClass'));     $creator->expects($this->once())             ->method('createSomeClass')             ->will($this->returnValue($created));      // call someFoo() with the correct $arg     $creator->someFoo('foo'); } 

Keep in mind that because the instance is creating another instance of the same class, two instances will normally be involved. You could use the same mock instance here if it makes it clearer.

function testSomeFoo() {     $fixture = $this->getMock('someClass', array('createSomeClass', 'someOtherFoo'));      // mock createSomeClass() to return the mock     $fixture->expects($this->once())             ->method('createSomeClass')             ->will($this->returnValue($fixture));      // mock someOtherFoo() to ensure it gets the correct value for $arg     $fixture->expects($this->once())             ->method('someOtherFoo')             ->with('foo');      // call someFoo() with the correct $arg     $fixture->someFoo('foo'); } 
like image 177
David Harkness Avatar answered Oct 13 '22 14:10

David Harkness