问题
I'm getting to grips with unit testing and learning how to break up my code into testable bits, but one thing I'm not clear on is how I can write my 'higher-level' code, such as my controller actions, so that testing the controller doesn't require going through the actual data layer (which is independently tested elsewhere in my test suite).
For example - I have a user validation which takes a username/password and validates their account and returns login success/failure:
class Api_AuthController extends Zend_Controller_Action
{
public function validateUserAction()
{
// extract, clean and validate $username from POSTed data
// extract, clean and validate $password from POSTed data
// access the data layer
$accountMapper = new Application_Model_Mapper_Account();
$accounts = $accountMapper(find(array('username' => $username, 'password' => $password));
if (count($accounts) == 1) {
// success
} else {
// failure
}
}
}
As mentioned - Application_Model_Mapper_Account
and its find()
method have been tested in another unit test, so it's superfluous (and as I understand unit testing - undesirable, not to mention it's unnecessarily slowing down my tests) to test again here, as all I really need to test is the ability of the action to discriminate the two possible results of the find function.
So - how do I substitute mocks for the mapper and model into this action so I can limit the scope of the validateUserAction tests?
回答1:
I'm from the .net world, but we use Inversion of Control containers to allow us to inject any dependencies into the controller. This way you can mock any dependencies to behave how you want and focus your testing on the actions.
来源:https://stackoverflow.com/questions/6222001/how-to-decouple-my-data-layer-better-and-restrict-the-scope-of-my-unit-tests