测试领域服务

我们希望对领域服务进行测试,并且希望从客户端的角度对领域服务进行建模,同时我们希望测试能够反映出领域服务的使用方式。

此时进行测试是否为时已晚?

在前面的章节中,我正式向大家介绍了測试驱动开发,也向大家展示了一些例子。在本章中我并没有这么做,单单只是因为我希望尽早地与大家讨论对领域服务的实现。但是,这的确也说明测试先行的策略并不总是必要的,虽然不这样做可能会遗漏一些建模关注点。

以下测试展示了如何正确地使用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 编写测试。

results matching ""

    No results matching ""