我想编写一个测试来检查给定命名空间中的类。必须检查返回任何类型列表的类的所有方法,如果它们返回 null。如果是这样,测试必须失败。

类/方法本身也有应该自动模拟的依赖项(构造函数参数和方法参数)。

AutoFixture 是否有一种机制来检查返回任何类型列表的方法从不返回 null?

示例类:

public class UserService
{
    private readonly IRemotingFacade _remotingFacade;

    public UserService(IRemotingFacade remotingFacade)
    {
        _remotingFacade = remotingFacade;
    }

    // directly return a list
    public IEnumerable<User> GetUsers()
    {

    }

    // directly return a list, pass method parameters
    public IEnumerable<User> GetUsers(string filter)
    {

    }

    // wrapped list
    public IBusinessResponse<IEnumerable<User>> GetUsers()
    {

    }


    // wrapped list, pass method parameters
    public IBusinessResponse<IEnumerable<User>> GetUsers(string filter)
    {

    }
}

所以请考虑列表可以包含在另一个对象中。

最佳答案

AutoFixture 3.18.0 引入了一个名为 Idioms.FsCheck 的新胶水库,它使用 FsCheck 来实现可重用的
名为 ReturnValueMustNotBeNullAssertion 的断言。

这个新断言验证(或至少使可能)返回值 (Query) 的方法不返回 null。

安装

NuGet 上提供了 Idioms.FsCheck:

PM> Install-Package AutoFixture.Idioms.FsCheck

场景
UserService 使用 IRemotingFacade 的注入(inject)实例并公开两个 [1] 查询:
  • 用户[] GetUsers()
  • 用户[] GetUsers(int)

  • 场景 #1 :注入(inject)的 IRemotingFacade 实例返回 null:
    [Theory, UnitTestConventions]
    public void Scenario1(
        ISpecimenBuilder builder,
        [Frozen]Mock<IRemotingFacade> stub)
    {
        stub.Setup(x => x.GetUsers()).Returns((User[])null);
    
        var sut = from x in new Methods<UserService>() select x.GetUsers();
    
        var assertion = new ReturnValueMustNotBeNullAssertion(builder);
        Assert.Throws<ReturnValueMustNotBeNullException>(() =>
            assertion.Verify(sut));
    }
    

    场景 #2 :注入(inject)的 IRemotingFacade 实例不返回 null:
    [Theory, UnitTestConventions]
    public void Scenario2(
        ISpecimenBuilder builder,
        [Frozen]Mock<IRemotingFacade> stub,
        User[] users)
    {
        stub.Setup(x => x.GetUsers()).Returns(users);
    
        var sut = from x in new Methods<UserService>() select x.GetUsers();
    
        var assertion = new ReturnValueMustNotBeNullAssertion(builder);
        Assert.DoesNotThrow(() => assertion.Verify(sut));
    }
    

    场景 3 :如果 i 是 -1 GetUsers(int) 返回 null:
    [Theory, UnitTestConventions]
    public void Scenario3(
        ISpecimenBuilder builder,
        [Frozen]Mock<IRemotingFacade> stub,
        User[] users)
    {
        stub.Setup(x => x.GetUsers()).Returns(users);
    
        var sut = from x in new Methods<UserService>()
                  select x.GetUsers(default(int));
    
        var assertion = new ReturnValueMustNotBeNullAssertion(builder);
        Assert.Throws<ReturnValueMustNotBeNullException>(
            () => assertion.Verify(sut));
    }
    

    备注

    If you only have F# 3.1 installed ,您还可以在 app.config 文件中添加程序集绑定(bind)重定向:
    <dependentAssembly>
      <assemblyIdentity name="FSharp.Core"
                        publicKeyToken="b03f5f7f11d50a3a"
                        culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-4.3.1.0"
                       newVersion="4.3.1.0" />
    </dependentAssembly>
    
    UnitTestConventionsAttribute 定义为:
    internal class UnitTestConventionsAttribute : AutoDataAttribute
    {
        internal UnitTestConventionsAttribute()
            : base(new Fixture().Customize(new AutoMoqCustomization()))
        {
        }
    }
    

    反射查询使用 Albedo 执行。

    [1] 为了演示,我简化了 original code 如下:
    public class User
    {
    }
    
    public interface IRemotingFacade
    {
        User[] GetUsers();
    }
    
    public class UserService
    {
        private readonly IRemotingFacade remotingFacade;
    
        public UserService(IRemotingFacade remotingFacade)
        {
            if (remotingFacade == null)
                throw new ArgumentNullException("remotingFacade");
    
            this.remotingFacade = remotingFacade;
        }
    
        public User[] GetUsers()
        {
            return this.remotingFacade.GetUsers();
        }
    
        public User[] GetUsers(int i)
        {
            if (i == -1)
                return null;
    
            return this.remotingFacade.GetUsers();
        }
    }
    

    10-07 19:45
    查看更多