测试领域服务
我们希望对领域服务进行测试,并且希望从客户端的角度对领域服务进行建模,同时我们希望测试能够反映出领域服务的使用方式。
此时进行测试是否为时已晚?
在前面的章节中,我正式向大家介绍了測试驱动开发,也向大家展示了一些例子。在本章中我并没有这么做,单单只是因为我希望尽早地与大家讨论对领域服务的实现。但是,这的确也说明测试先行的策略并不总是必要的,虽然不这样做可能会遗漏一些建模关注点。
以下测试展示了如何正确地使用AuthenticationService,首先我们测试认证成的场景:
public class AuthenticationServiceTest
extends IdentityTest {
public void testAuthenticationSuccess() throws Exception {
User user = this.getUserFixture();
DomainRegistry
.userRepository()
.add(user);
UserDescriptor userDescriptor =
DomainRegistry
.authenticationService()
.authenticate(
user.tenantId(),
user.username(),
FIXTURE_PASSWORD);
assertNotNull(userDescriptor);
assertEquals(user.tenantId(), userDescriptor.tenantId());
assertEquals(user.username(), userDescriptor.username());
assertEquals(user.person().emailAddress(),
userDescriptor.emailAddress());
}
...
}
上面的例子向我们展示了应用服务的客户端是如何使用AuthenticationService 的。这是一个顺利的使用场景,此时一个User得到了成功的认证。
请注意,这里的资源库可以是真实产品环境下的资源库,也可以是内存资源库,还可以是模拟(mock)资源库。当然,采用哪种类型的资源库只是一个选择问题。
接下来,我们需要测试认证失败的场景:
public void testAuthenticationTenantFailure() throws Exception {
User user = this.getUserFixture();
DomainRegistry.userRepository().add(user);
TenantId bogusTenantId = DomainRegistry.tenantRepository().nextIdentity();
UserDescriptor userDescriptor = DomainRegistry.authenticationService().authenticate(
bogusTenantId, // bogus
user.username(),
FIXTURE_PASSWORD);
assertNull(userDescriptor);
}
在上例中,由于我们传人的Tenantld和创建User时的Tenantld不一样,认证过程将失败。此外,如果我们传入的username不合法,认证过程也将失败:
public void testAuthenticationUsernameFailure() throws Exception {
User user = this.getUserFixture();
DomainRegistry
.userRepository()
.add(user);
UserDescriptor userDescriptor =
DomainRegistry
.authenticationService()
.authenticate(
user.tenantId(),
"bogususername",
user.password());
assertNull(userDescriptor);
}
在上例中,由于我们传入了一个错误的username,认证过程也将失败。最后, 还有另外一个认证失败的场景:
public void testAuthenticationPasswordFailure() throws Exception {
User user = this.getUserFixture();
DomainRegistry
.userRepository()
.add(user);
UserDescriptor userDescriptor =
DomainRegistry
.authenticationService()
.authenticate(
user.tenantId(),
user.username(),
"passw0rd");
assertNull(userDescriptor);
}
}
在上例中,我们传入了一个错误的password,认证过程同样会失败。在所有失败的认证过程中,返回的UserDescriptor都将是null。客户端需要知道这样的细节,因为返回的null表示对一个User的认证不成功。同时,它表示认证失败并不是一个异常性错误,而是该领域中本来就存在的一种可能。否则,我们需要从领域服务中抛出 AuthenticationFai ledExcept ion 异常。
事实上,我们还缺少了几个测试用例。对于一个Tenant处于失活状态和一个User处于未激活状态的场景,请读者自行完成测试。在此之后,你可以继续为BusinessPriorityCalculator 编写测试。