实体框架 TDD,如何对所需字段进行单元测试模型

发布于 2024-12-05 09:32:30 字数 877 浏览 1 评论 0原文

我开始使用 Entity Framework 4.1 对以下类使用 TDD:

    public class Agent
    {
        // Primary key
        public int ID { get; set; }

        [Required]
        public string Name { get; set; }

        public string Address { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Phone1 { get; set; }
    }

我的断言将失败:

    /// <summary>
    ///A test for Agent Constructor need have name
    ///</summary>
    [TestMethod()]
    public void AgentConstructorTest()
    {
        Agent target = new Agent();
        Assert.IsNull(target);
    }

当我查看生成的目标对象时,它是使用 ID = 0 创建的。我如何测试 Name 是那么需要吗?

如果 Name 字段是必需的,我如何仍然创建 Agent 对象?真实ID什么时候分配?要测试模型本身,我是否需要创建/模拟一个 DbContext 才能分配 ID?

I am start using TDD for the following class using Entity Framework 4.1:

    public class Agent
    {
        // Primary key
        public int ID { get; set; }

        [Required]
        public string Name { get; set; }

        public string Address { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Phone1 { get; set; }
    }

My assertion will fail:

    /// <summary>
    ///A test for Agent Constructor need have name
    ///</summary>
    [TestMethod()]
    public void AgentConstructorTest()
    {
        Agent target = new Agent();
        Assert.IsNull(target);
    }

When I look at the generated target object, it is created with ID = 0. How could I test that Name is required then?

And if the Name field is required, how could I still create an Agent object? When will the real ID been assigned? To test model itself, do I need create/mockup a DbContext to be able to assigned a ID?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自由范儿 2024-12-12 09:32:30

请记住,您在这里只是处理 POCO 类 - 没有什么神奇的事情会导致 Agent 类的构造失败,仅仅因为您在其属性之一上放置了自定义属性。

实体框架在验证和数据映射期间检查自定义属性 - 在这种情况下,它将检查 Required 属性,并且仅在相应的字符串属性不为 null 并且它还会将 Name 映射到数据库中的不可为空列。

为了反映这一点,您可以在单元测试中编写一个自定义验证例程来执行相同的检查,即确保用 Required 属性修饰的所有属性确实具有值,即类似这样的内容:

[TestMethod()]
public void AgentWithNoNameIsInvalid()
{
    Agent target = new Agent();

    Assert.IsFalse(IsValid(target));
}

这确实感觉您现在正在测试 EF,而不是您的代码。

由于 ID 是您的主键,因此仅当实体已提交到数据库时才会分配它。因此,是的,对于完整测试,您将必须模拟一个工作单元和一个为您执行此操作的上下文。不过,IQueryableIEnumerable 之间存在许多陷阱,并且存在微妙(而不是那么微妙)的差异,这使得这种方法非常脆弱。

就我个人而言,我建议您基于具有已知内容的单独测试数据库使用 EF 进行集成测试,并根据此测试数据库编写单元测试和预期结果 - 这可能不是真正的 TDD,但我发现这是确保唯一的方法我正在测试正确的东西。

Keep in mind that your are just dealing with POCO classes here - there is no magic going on that would allow the construction of the Agent class to fail just because you have put a custom attribute on one of its properties.

Entity framework is checking for custom attributes during its validation and for data mapping - in this case it will check for the Required attribute and only declare the entity as "valid" if the corresponding string property is not null and also it will map Name to a non-nullable column in the database.

To mirror that you could write a custom validation routine in your unit test that performs the same checks, i.e. makes sure that all properties that are decorated with the Required attribute indeed have a value, i.e something like this:

[TestMethod()]
public void AgentWithNoNameIsInvalid()
{
    Agent target = new Agent();

    Assert.IsFalse(IsValid(target));
}

This does feel like you are testing EF now though, not your code.

Since the ID is your primary key it will only be assigned when the entity has been committed to the database. So yes for full testing you will have to mock a unit of work and a context that does this for you as well. There are many pitfalls though and subtle (and not so subtle) differences between IQueryable<T> and IEnumerable<T> that makes this approach very fragile.

Personally I would recommend you do integration testing with EF based on a separate test database with known content and write your unit tests and expected results based on this test database - this might not be true TDD but I found it is the only way to be sure that I am testing the right thing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文