在 Automoq 和 Autofixture 中使用内联数据时如何运行单元测试

发布于 2025-01-11 04:11:14 字数 2436 浏览 3 评论 0原文

我在现有项目上创建了一些单元测试。我正在使用 AutoMoq 将数据注入到一些测试中。运行测试后,它抱怨递归错误。我使用以下代码解决了该错误:

public sealed class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute()
        : base(() => new Fixture().Customize(new DomainCustomization()))
    {
    }
}

public class OmitRecursionCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b =>
        fixture.Behaviors.Remove(b));
        fixture.Behaviors.Add(new OmitOnRecursionBehavior());
    }
}

public class DomainCustomization : CompositeCustomization
{
    public DomainCustomization()
        : base(
            new AutoMoqCustomization(),
            new SupportMutableValueTypesCustomization(),
            new OmitRecursionCustomization())
    {
    }
}

解决递归错误后,测试将无法运行。调试输出一直显示线程已退出。然后,我创建了一些示例类来测试我的设置,除了现有的项目类测试之外,它们都运行。

我正在为其编写测试的类的示例如下:

public partial class BusinessContact
{
    public int BusinessContactId { get; set; }
    public int BusinessId { get; set; }
    public int ContactId { get; set; }
    public int? AddressId { get; set; }
    public int? EmailId { get; set; }
    public BusinessContactType.TypeID BusinessContactTypeId { get; set; }

    [Column(TypeName = "smalldatetime")]
    public DateTime DateLastModified { get; set; }

    [StringLength(450)]
    public string ModifiedByUserId { get; set; }

    [ForeignKey("AddressId")]
    [InverseProperty("BusinessContact")]
    public virtual Address Address { get; set; }

    [ForeignKey("BusinessId")]
    [InverseProperty("BusinessContact")]
    public virtual Business Business { get; set; }

    [ForeignKey("BusinessContactTypeId")]
    [InverseProperty("BusinessContact")]
    public virtual BusinessContactType BusinessContactType { get; set; }

    [ForeignKey("ContactId")]
    [InverseProperty("BusinessContact")]
    public virtual Contact Contact { get; set; }

    [ForeignKey("EmailId")]
    [InverseProperty("BusinessContact")]
    public virtual Email Email { get; set; }
}

上述类的示例测试如下:

    [Theory]
    [AutoMoqData]
    public void ValidateMandatoryField(BusinessContact _sut)
    {
        Assert.NotNull(_sut.BusinessId);
        Assert.True(_sut.BusinessId > 0);
    }

我打算发送多个内联数据,在其中我可以设置某些类属性的值来测试我正在寻找的行为。

有人可以告诉我可能出了什么问题吗?

谢谢。

I created some unit tests on an existing project. I am using AutoMoq to inject data into some of the tests. Upon running the test, it complains of recursion error. I solved the error using the below code:

public sealed class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute()
        : base(() => new Fixture().Customize(new DomainCustomization()))
    {
    }
}

public class OmitRecursionCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b =>
        fixture.Behaviors.Remove(b));
        fixture.Behaviors.Add(new OmitOnRecursionBehavior());
    }
}

public class DomainCustomization : CompositeCustomization
{
    public DomainCustomization()
        : base(
            new AutoMoqCustomization(),
            new SupportMutableValueTypesCustomization(),
            new OmitRecursionCustomization())
    {
    }
}

After solving the recursion error, the test won't run. The debug output keeps saying the thread has exited. I then created some sample classes to test my setup and they all run, except the existing project classes tests.

A sample of a class I am writing test for is this:

public partial class BusinessContact
{
    public int BusinessContactId { get; set; }
    public int BusinessId { get; set; }
    public int ContactId { get; set; }
    public int? AddressId { get; set; }
    public int? EmailId { get; set; }
    public BusinessContactType.TypeID BusinessContactTypeId { get; set; }

    [Column(TypeName = "smalldatetime")]
    public DateTime DateLastModified { get; set; }

    [StringLength(450)]
    public string ModifiedByUserId { get; set; }

    [ForeignKey("AddressId")]
    [InverseProperty("BusinessContact")]
    public virtual Address Address { get; set; }

    [ForeignKey("BusinessId")]
    [InverseProperty("BusinessContact")]
    public virtual Business Business { get; set; }

    [ForeignKey("BusinessContactTypeId")]
    [InverseProperty("BusinessContact")]
    public virtual BusinessContactType BusinessContactType { get; set; }

    [ForeignKey("ContactId")]
    [InverseProperty("BusinessContact")]
    public virtual Contact Contact { get; set; }

    [ForeignKey("EmailId")]
    [InverseProperty("BusinessContact")]
    public virtual Email Email { get; set; }
}

A sample test for the above class is this:

    [Theory]
    [AutoMoqData]
    public void ValidateMandatoryField(BusinessContact _sut)
    {
        Assert.NotNull(_sut.BusinessId);
        Assert.True(_sut.BusinessId > 0);
    }

I intend to send multiple inline data where I can set the value some of the class properties to test the behaviours I am looking for.

Could someone please enlighten me on what might be wrong.

Thank you.

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

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

发布评论

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

评论(1

困倦 2025-01-18 04:11:14

这篇文章https://stackoverflow.com/a/70957998/3036650解决了我对这个问题的挑战。该问题与使用实体框架时引起的循环引用有关。所以该代码完全可以替换或添加到OmitRecursionCustomization类中customize方法的内容中。该类现在看起来像这样:

    {
        public void Customize(IFixture fixture)
        {
            fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b =>
            fixture.Behaviors.Remove(b));
            fixture.Behaviors.Add(new OmitOnRecursionBehavior());
            fixture.Customizations.Add(new IgnoreVirtualMembers());
        }
    }

其用法如下:

var fixture = new Fixture().Customize(new IgnoreVirtualMembersCustomisation());

This post https://stackoverflow.com/a/70957998/3036650 solved my challenge on this question. The issue has to do with circular reference caused when using Entity framework. So the code can totally replace or be added to the content of customize method in the OmitRecursionCustomization class. The class looks like this now:

    {
        public void Customize(IFixture fixture)
        {
            fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b =>
            fixture.Behaviors.Remove(b));
            fixture.Behaviors.Add(new OmitOnRecursionBehavior());
            fixture.Customizations.Add(new IgnoreVirtualMembers());
        }
    }

and it is used as follows:

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