Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# CodeAccessSecurityAttribute的模拟自定义实现_C#_Unit Testing_Moq - Fatal编程技术网

C# CodeAccessSecurityAttribute的模拟自定义实现

C# CodeAccessSecurityAttribute的模拟自定义实现,c#,unit-testing,moq,C#,Unit Testing,Moq,我有一个自定义的实现,即连接外部源以进行验证 [Serializable] [AttributeUsage(AttributeTargets.Method)] public class IsAuthorizedAttribute : CodeAccessSecurityAttribute { private static readonly PrincipalPermission Allowed = new PrincipalPermission(PermissionState.None)

我有一个自定义的实现,即连接外部源以进行验证

[Serializable]
[AttributeUsage(AttributeTargets.Method)]
public class IsAuthorizedAttribute : CodeAccessSecurityAttribute
{
    private static readonly PrincipalPermission Allowed = new PrincipalPermission(PermissionState.None);
    private static readonly PrincipalPermission NotAllowed = new PrincipalPermission(PermissionState.Unrestricted);

    public string EntityObject { get; set; }
    public string Field { get; set; }
    public char Expected { get; set; }

    public IsAuthorizedAttribute(SecurityAction action)
            : base(action)
    {
        //setup
    }

    public override IPermission CreatePermission()
    {
        return IsAuthorised(EntityObject, Field, Expected, ServicesConfiguration) ? Allowed : NotAllowed;
    }

    private static bool IsAuthorised(string entityObject, string field, char expected, ServicesConfiguration servicesConfiguration)
    {
        bool? response = null;
        //check external stuff
        return response ?? false;
    }
}
我已使用此属性装饰我的方法:

[IsAuthorized(SecurityAction.Demand, EntityObject = Fields.UserManagement, Field = Fields.AllowDisplay, Expected = '1')]
public List<Group> GetUserGroups()
{
    var response = new List<Group>();

    //Get the groups from the database
    var groups = groupManager.FindAll();

    //Map them to the output group type
    response = groups.Select(x => new Group()
    {
        ID = x.ID,
        Name = x.Name,
        Alias = x.Alias,
        Description = x.Description
    }).ToList();

    return response;
}
[TestMethod]
public void GetUserGroups_UserGroupsFound_UserGroupsReturned()
{
    Smock.Run(context =>
    {
        //Arrange
        Setup();

        m_Container
                    .RegisterMock<IGroupManager>()
                    .Setup(x => x.FindAllFromCache())
                    .Returns(new List<Concept.Security.MasterData.Domain.Group>()
                    {
                        new Concept.Security.MasterData.Domain.Group()
                        {
                            Name = "MyUserGroup",
                            Alias = "My User Group",
                            Description = "My user group description",
                            System = false,
                            Authorizations = "000001111100000000"
                        },
                        new Concept.Security.MasterData.Domain.Group()
                        {
                            Name = "MySecondUserGroup",
                            Alias = "My Second User Group",
                            Description = "My second user group description",
                            System = false,
                            Authorizations = "000000000000000000"
                        }
                    });

        var identityService = new UserManagementService(m_Container, m_UserAuthorizationManager.Object, m_IdentityService.Object);

        //** begin add mocked attribute **//
        //** end add mocked attribute **//

        //Act
        var response = identityService.GetUserGroups();

        //Assert
        Assert.AreEqual(2, response.Count);
        Assert.AreEqual(1, response.Where(x => x.Alias == "MyUserGroup").Count());
        Assert.AreEqual(1, response.Where(x => x.Alias == "MySecondUserGroup").Count());
        Assert.AreEqual(2, response.Where(x => x.Authorizations == null).Count());
    });
}
//** begin add mocked attribute **//
var identityService = new UserManagementService(m_Container, m_UserAuthorizationManager.Object, m_IdentityService.Object);

var IsAuthorizedAttribute = new Mock<IsAuthorizedAttribute>(MockBehavior.Strict, new object[] { SecurityAction.Demand });
IsAuthorizedAttribute.Setup(x => x.CreatePermission()).Returns(new PrincipalPermission(PermissionState.None));
TypeDescriptor.AddAttributes(identityService, IsAuthorizedAttribute.Object);
//** end add mocked attribute **//
现在我想对这个方法进行单元测试,但是属性被激发了。我尝试过一些东西来嘲弄这个属性,但没有成功

我用的是最小起订量和最小起订量

这是我的单元测试,没有该属性的模拟实例:

[IsAuthorized(SecurityAction.Demand, EntityObject = Fields.UserManagement, Field = Fields.AllowDisplay, Expected = '1')]
public List<Group> GetUserGroups()
{
    var response = new List<Group>();

    //Get the groups from the database
    var groups = groupManager.FindAll();

    //Map them to the output group type
    response = groups.Select(x => new Group()
    {
        ID = x.ID,
        Name = x.Name,
        Alias = x.Alias,
        Description = x.Description
    }).ToList();

    return response;
}
[TestMethod]
public void GetUserGroups_UserGroupsFound_UserGroupsReturned()
{
    Smock.Run(context =>
    {
        //Arrange
        Setup();

        m_Container
                    .RegisterMock<IGroupManager>()
                    .Setup(x => x.FindAllFromCache())
                    .Returns(new List<Concept.Security.MasterData.Domain.Group>()
                    {
                        new Concept.Security.MasterData.Domain.Group()
                        {
                            Name = "MyUserGroup",
                            Alias = "My User Group",
                            Description = "My user group description",
                            System = false,
                            Authorizations = "000001111100000000"
                        },
                        new Concept.Security.MasterData.Domain.Group()
                        {
                            Name = "MySecondUserGroup",
                            Alias = "My Second User Group",
                            Description = "My second user group description",
                            System = false,
                            Authorizations = "000000000000000000"
                        }
                    });

        var identityService = new UserManagementService(m_Container, m_UserAuthorizationManager.Object, m_IdentityService.Object);

        //** begin add mocked attribute **//
        //** end add mocked attribute **//

        //Act
        var response = identityService.GetUserGroups();

        //Assert
        Assert.AreEqual(2, response.Count);
        Assert.AreEqual(1, response.Where(x => x.Alias == "MyUserGroup").Count());
        Assert.AreEqual(1, response.Where(x => x.Alias == "MySecondUserGroup").Count());
        Assert.AreEqual(2, response.Where(x => x.Authorizations == null).Count());
    });
}
//** begin add mocked attribute **//
var identityService = new UserManagementService(m_Container, m_UserAuthorizationManager.Object, m_IdentityService.Object);

var IsAuthorizedAttribute = new Mock<IsAuthorizedAttribute>(MockBehavior.Strict, new object[] { SecurityAction.Demand });
IsAuthorizedAttribute.Setup(x => x.CreatePermission()).Returns(new PrincipalPermission(PermissionState.None));
TypeDescriptor.AddAttributes(identityService, IsAuthorizedAttribute.Object);
//** end add mocked attribute **//
运行此操作会导致异常,因为该属性尝试连接外部服务,但它们没有也无法设置为接收请求

因此,我尝试添加一个模拟属性:

[IsAuthorized(SecurityAction.Demand, EntityObject = Fields.UserManagement, Field = Fields.AllowDisplay, Expected = '1')]
public List<Group> GetUserGroups()
{
    var response = new List<Group>();

    //Get the groups from the database
    var groups = groupManager.FindAll();

    //Map them to the output group type
    response = groups.Select(x => new Group()
    {
        ID = x.ID,
        Name = x.Name,
        Alias = x.Alias,
        Description = x.Description
    }).ToList();

    return response;
}
[TestMethod]
public void GetUserGroups_UserGroupsFound_UserGroupsReturned()
{
    Smock.Run(context =>
    {
        //Arrange
        Setup();

        m_Container
                    .RegisterMock<IGroupManager>()
                    .Setup(x => x.FindAllFromCache())
                    .Returns(new List<Concept.Security.MasterData.Domain.Group>()
                    {
                        new Concept.Security.MasterData.Domain.Group()
                        {
                            Name = "MyUserGroup",
                            Alias = "My User Group",
                            Description = "My user group description",
                            System = false,
                            Authorizations = "000001111100000000"
                        },
                        new Concept.Security.MasterData.Domain.Group()
                        {
                            Name = "MySecondUserGroup",
                            Alias = "My Second User Group",
                            Description = "My second user group description",
                            System = false,
                            Authorizations = "000000000000000000"
                        }
                    });

        var identityService = new UserManagementService(m_Container, m_UserAuthorizationManager.Object, m_IdentityService.Object);

        //** begin add mocked attribute **//
        //** end add mocked attribute **//

        //Act
        var response = identityService.GetUserGroups();

        //Assert
        Assert.AreEqual(2, response.Count);
        Assert.AreEqual(1, response.Where(x => x.Alias == "MyUserGroup").Count());
        Assert.AreEqual(1, response.Where(x => x.Alias == "MySecondUserGroup").Count());
        Assert.AreEqual(2, response.Where(x => x.Authorizations == null).Count());
    });
}
//** begin add mocked attribute **//
var identityService = new UserManagementService(m_Container, m_UserAuthorizationManager.Object, m_IdentityService.Object);

var IsAuthorizedAttribute = new Mock<IsAuthorizedAttribute>(MockBehavior.Strict, new object[] { SecurityAction.Demand });
IsAuthorizedAttribute.Setup(x => x.CreatePermission()).Returns(new PrincipalPermission(PermissionState.None));
TypeDescriptor.AddAttributes(identityService, IsAuthorizedAttribute.Object);
//** end add mocked attribute **//
但是这个调用了我设置外部源的属性的构造函数。当我将此构造函数放入try/catch并以静默方式处理异常时,ISAuthorizeDatAttribute上出现错误。找不到对象


还有哪些选项不触发该属性?

构造函数不应访问外部;否则,正如您所知,很难绕过测试

一个简单的方法是使静态布尔场绕过。这看起来不太好,但也许足够了

public class IsAuthorizedAttribute : CodeAccessSecurityAttribute
{
    // set true in the test initialization
    private static bool s_byPass;

    public IsAuthorizedAttribute(SecurityAction action) : base(action)
    {
        if (!s_byPass)
        {
           // setup
        }
    }

    private static bool IsAuthorised(string entityObject, string field, char expected, ServicesConfiguration servicesConfiguration)
    {
        if (s_byPass) { return true; }

        //check external stuff
    }
}
另一个更好的方法是将外部依赖项提取到另一个类,以便可以模拟它。模拟外部依赖关系是单元测试的典型模式

public class IsAuthorizedAttribute : CodeAccessSecurityAttribute
{
    // set mock here in the test initialization.
    // I assume external accessor can be a static field.
    private static ExternalAccessor m_accessor = new ExternalAccessor();

    private static bool IsAuthorised(string entityObject, string field, char expected, ServicesConfiguration servicesConfiguration)
    {
        return m_accessor.Check();
    }
}

public class ExternalAccessor
{
    private bool m_initialized;

    private void Setup()
    {
        // setup
        m_initialized = true;
    }

    public virtual bool Check()
    {
        // You can call setup anytime but the constructor.
        if (!m_initialized) { Setup(); }

        // check external stuff
    }
}

您必须提供一个可用于重现问题的属性。另一方面,这清楚地表明该属性试图执行过多的ie单一责任原则SRP违反。违背了与.net实践相关的属性的预期目的。@CyclingFreak您能详细介绍一下。。。当我将此构造函数放入try/catch并静默处理异常时,ISAuthorizeDatAttribute.Object对象上出现错误。您面临什么异常?你用什么方法面对它?我用了第二种方法。我应该自己考虑使用一个可以被嘲笑的外部类。