如何使用AutoFixture和AutoMoqCustomization设置某些属性并将其他属性保留为默认设置?

时间:2020-03-18 06:28:41

标签: moq xunit autofixture

我是自动修复的新手,希望您能为您提供帮助。在使用XUnit的[Theory]属性和AutoDataAttribute 时,如何在对象中设置某些属性,而将其他属性保留为AutoFixture的默认设置-

例如,在下面基于杰森·罗伯特(Jason Robert)的Pluralsight课程设计的“机场”示例中,设置属性(或“机场”对象)时,例如

f.Customize<Mock<IAirport>>(c => c.Do(m => m.SetupGet(i => i.code).Returns("NOO")));

其他属性通常为null,或者我必须手动设置它们而不是让AutoFixture来做。我更喜欢使用更简洁的代码,其中fixtureFactory设置Airport的所有属性,以便仅通过单个Airport参数传递V2单元测试。

因此,在fixtureFactory中

  • 如何设置多个属性?
  • 如何使用默认的AutoFixture值,而不是将未初始化的值保留为 空值?

谢谢!

using AutoFixture;
using AutoFixture.AutoMoq;
using AutoFixture.Xunit2;
using Moq;
using System;
using Xunit;
namespace AirportTesterWithAutoFixture
{
    public interface IAirport
    {
        string city { get; set; }
        string code { get; set; }
        string country { get; set; }
        string name { get; set; }

        void CallAirTrafficControl();
    }
    public class Airport : IAirport
    {
        public string name { get; set; }
        public string city { get; set; }
        public string code { get; set; }
        public string country { get; set; }
        public Airport()
        {
        }
        public Airport(string name, string code, string country, string city)
        {
            this.name = name;
            this.code = code;
            this.country = country;
            this.city = city;
        }
        public void CallAirTrafficControl()
        {
            if (this.country.Equals("Canada") && this.code.StartsWith("Y"))
            {
                // Send "Bonjour!"();
            }
            else
            {
                throw new Exception("Invalid code for Canada");
            }
        }
    }
    public class UnitTest1
    {
        [Fact]
        public void V1_Validate_ExceptionThrown_ForInvalidCanadianAirportCode()
        {
            var fixture = new Fixture();
            var sut = fixture.Create<Airport>();
            // Overwrite code and country with invalid setting for Canada.
            sut.country = "Canada";
            sut.code = "NOT";
            Assert.ThrowsAny<Exception>(() => sut.CallAirTrafficControl());
        }
        [Theory]
        [AutoMoqInvalidAirportDataAttribute]
        public void V2_Validate_ExceptionThrown_ForInvalidCanadianAirportCode(IAirport sut, string name, string city)
        {
            Airport airport = new Airport(name, sut.code, sut.country, city);
            Assert.ThrowsAny<Exception>(() => airport.CallAirTrafficControl());
        }
    }
    // https://stackoverflow.com/questions/58998834/how-to-use-ifixture-buildt-with-automoqcustomization-when-t-is-an-interface
    public class AutoMoqInvalidAirportDataAttribute : AutoDataAttribute
    {
        public static Func<IFixture> fixtureFactory = () =>
        {
            IFixture f = new Fixture().Customize(new AutoMoqCustomization());
            f.RepeatCount = 5;
    // How do you set MULTIPLE properties?
    // How does one use the default AutoFixture values rather than leaving the uninitialized values as null?
    // Can one pass a custom property used earlier in the Fixture creation process to another custom property used later?
    f.Customize<Mock<IAirport>>(c => c.Do(m => m.SetupGet(i => i.code).Returns("NOT")));
            return f;
        };
        public AutoMoqInvalidAirportDataAttribute() : base(fixtureFactory)
        {
        }
    }
}

1 个答案:

答案 0 :(得分:1)

默认情况下,AutoFixture不会填充模拟属性,但是可以完成。这些博客文章描述了如何做到这一点:

https://blog.ploeh.dk/2013/04/05/how-to-configure-automoq-to-set-up-all-properties/

https://blog.ploeh.dk/2013/04/08/how-to-automatically-populate-properties-with-automoq/

但是,AutoFixture的作者不推荐这种方法,因为他认为接口中的属性声明是一种设计气味。 不幸的是,我找不到关于此主题的原始讨论,但在评论中它隐藏在StackOverflow的某个位置。翻阅Mark Seemann的个人资料,也许您就可以找到它。