【发布时间】:2014-06-27 08:23:01
【问题描述】:
我正在使用 Laravel 开发 Web 应用程序,这个 Web 应用程序必须连接到内部服务。我选择在这个项目中进行 TDD,现在我面临着太多依赖项无法模拟的问题。
在RegisterController,我们允许用户登录并升级他们的帐户类型,见下面的代码:
public function loginForUpgradeAccount() {
$data = Input::only('email', 'hashedPassword');
if (!empty($data['email']) && !empty($data['hashedPassword'])) {
$email = $data['email'];
$hashedPassword = $data['hashedPassword'];
$login = $this->createLoginServiceConnector();
$token = $login->withEmailAndHashedPassword($email, $hashedPassword);
if ($token) {
$profile = $this->createProfileServiceConnector($token);
if ($profile->getData()['secret_code'] != Session::get('ThirdPartyData')['secret_code']) {
return $this->buildErrorJsonResponse('UPGD-002', 'SecretCode not match with Third party', 400);
}
else {
if ($profile->getData()['profile_type'] == 'consumer')
return $this->buildErrorJsonResponse('UPGD-003', 'Profile type is consumer', 400);
else //has to call internal upgrade api
}
}
}
return $this->buildErrorJsonResponse('UPGD-001', 'Wrong email or password', 400);
}
public function createLoginServiceConnector() {
return new Login(ApiInvokerFactory::createApiJsonInvoker());
}
public function createProfileServiceConnector($token) {
return new Profile(ApiInvokerFactory::createApiJsonInvoker(), $token);
}
测试代码示例如下:
public function test_loginForUpgrade_must_return_error_code_UPGD_002_when_secret_code_not_match_with_third_party_data() {
$data = array('email' => 'correct@example.com', 'hashedPassword' => '123333');
$profileData = array(
'secret_code' => 'abcdefg',
);
Session::put('ThirdPartyData', array('secret_code' => 'hijklmnop'));
Input::shouldReceive('only')
->with('email', 'hashedPassword')
->andReturn($data);
$login = Mockery::mock('Login');
/** @var $login RegisterController|\Mockery\MockInterface */
$ctrl = Mockery::mock('RegisterController');
$ctrl->shouldDeferMissing();
/** @var Profile||MockInterface $profile */
$profile = Mockery::mock('Profile');
$ctrl->shouldReceive('createLoginServiceConnector')
->andReturn($login);
$login->shouldReceive('withEmailAndHashedPassword')
->with($data['email'], $data['hashedPassword'])
->andReturn('correcttokenlogin');
$ctrl->shouldReceive('createProfileServiceConnector')
->with('correct_tokenlogin')
->andReturn($profile);
$profile->shouldReceive('getData')
->andReturn($profileData);
$result = $ctrl->loginForUpgrade();
$response = json_decode($result->getContent(), true);
$this->assertEquals('UPGD-002', $response['errorCode']);
}
这只是一个示例测试用例,对于一个控制器操作中的其他场景,我有非常相同的代码,例如错误的电子邮件或密码,配置文件类型是消费者等等。
我认为很难维护像这样凌乱的测试代码,如果有一天我们的升级流程发生变化或需要更多条件来升级,这会破坏我的所有测试,我必须删除并重新编写所有代码。
我是否正确地进行了单元测试和 TDD?
请给我正确的建议。
【问题讨论】:
标签: unit-testing laravel mocking tdd