单元测试包含从数据库填充的列表的域模型



我目前正在为我的域模型编写单元测试。

为了提供一些上下文,我有一个Role Group类,它有一个角色列表,它还有一个当前分配了该角色组的用户列表。

角色组被分配给用户,因此执行此操作的所有方法都在用户域模型中。这意味着角色组端的Users属性基本上是从数据库中提取的。

角色组和用户都是聚合根,它们都可以单独存在。

单元测试包含从数据库填充的列表的域模型

我正在努力的是,我无法测试下面的CanArchive方法,因为我无法将用户添加到属性中。除了使用Add方法之外,我不想使用它,因为它打破了域模型控制自己数据的整个想法。

所以我不确定我的域模型是否是错误的,或者这个逻辑是否应该放在服务中,因为它是两个聚合根之间的交互。

角色组类:

    public bool Archived { get; private set; }
    public int Id { get; private set; }
    public string Name { get; private set; }
    public virtual IList<Role> Roles { get; private set; }
    public virtual IList<User> Users { get; private set; }

更新存档方法:

    private void UpdateArchived(bool archived)
    {
        if (archived && !CanArchive())
        {
            throw new InvalidOperationException("Role Group can not be archvied.");
        }
        Archived = archived;
    }

检查角色组是否可以存档的方法

    private bool CanArchive()
    {
        if (Users.Count > 0)
        {
            return false;
        }
        return true;
    }

方法,该方法在User类中设置用户的角色组当在用户界面中创建或更新用户时,会调用此操作。

    private void UpdateRoleGroup(RoleGroup roleGroup)
    {
        if (roleGroup == null)
        {
            throw new ArgumentNullException("roleGroup", "Role Group can not be null.");
        }
        RoleGroup = roleGroup;
    }

几个想法:

  • 对域对象进行单元测试不应该依赖于持久层的东西。一旦你做到了这一点,你就有了一个集成测试。

  • 在DDD中,通过数据库集成两个聚合之间的更改理论上不是一个好主意。由User.UpdateRoleGroup()引起的更改应该保留在User聚合中,或者触发其他聚合上的公共域方法对其进行突变(以最终一致的方式)。如果这些方法是公开的,那么它们也应该可以从测试中访问。

  • 对于EntityFramework,这些都不重要,因为它不擅长建模只读集合,而且很可能会有一个可变的Users列表。我不认为在测试中调用roleGroup.Users.Add(...)来设置数据是一个大问题,尽管您不应该在生产代码中这样做。也许,正如@NikolaiDante所建议的那样,将internalinternalsVisibleTo列为您的测试项目,并将其封装到公共只读集合中,会降低风险。

我正在努力的是,我无法测试下面的CanArchive方法,因为我无法将用户添加到属性中。

从数据库加载RoleGroup实例的框架如何填充用户?这是你必须问自己的问题,为你的单元测试找到解决方案。只要用同样的方法。

我不知道你用什么语言。例如,在Java中,您可以使用反射api来设置私有字段。还有很多测试框架为这项工作提供了方便的方法,例如Deencaapsulation或Whitebox。

最新更新