In our attempts to perform unit tests we have the following situation:
We have Controller that calls a component(c1). In this case the functions of c1 (In this case a component which calls Amazon AWS Cloud Search) are required to be mocked out in the case of the unit tests as I only care how the controller handles the response. I have looked thoroughly through the documentation and there is a setComponent function for the module, but not for the yii base. What I really want to do in this case is temporarily assign Yii::app()->c1 to be a PHPUnit Mock Class, so I can override the return values e.g.
Yii::app()->c1 = $this->getMock(‘SomeClass’, array(‘someFunction1’, ‘someFunction2’));
//Of course this is currently impossible in this syntax, I am simply demonstrating what I would LIKE to do
Through investigation I know I could create an actual Mock Component class and then in the test.php in the config directory, set it as ‘components’ => array(‘c1’=> array(‘class’=>‘mockClass’), however I do not want to have to override all the functions to return null (which PHPUnit mock already does) and write my own ->expects() method to handle different return values for different test cases.
I know I could also override the application using setApplication and feed in a mock application (as mentioned in thread /yiisoft/yii/issues/2389 on github.com, due to this being my first post I am unable to put the full url in.)to my unit tests. However in this example I only require a single specific mock component, and do not actually want to mock out my entire application.
I could of course not use Yii::app() in my controller and instead have components as instance variables of my class e.g
SomeClass {
private $c2
public function setC2($c2){
$this->c2 = $c2
}
}
Then call all my components inside the controller with $this->c2->function()
The issue we had with this was that programmers were putting the creation of these components inside the init() or __construct() function of our controller and components. The reasoning for this was to ensure those components were created when the Class was initialized so we could use them immediately. Due to this when they attempted to create the Component or Controller in a unit test, these init and construct methods were called and then the ACTUAL component was created. Although in this case were were able to override the component after, what this meant is that our unit tests were creating components that tried to connect with third party sources (something we do not want, we don’t want our unit tests to fail if for some reason a third party source is not reachable)
What I would prefer is to always call our "singleton" components using Yii::app()->someComponent->function() (in both unit tests and in our application), and then in the unit tests be able to override that someComponent at any time in my unit tests with a mock component.