如何为包含只读成员的接口创建单元测试存根?

时间:2010-03-29 18:01:37

标签: c# unit-testing interface properties readonly

我正在为IPrincipal上编写的扩展方法编写一些单元测试。为了提供帮助,我创建了几个辅助类(为简洁起见,省略了一些未实现的接口成员的代码):

public class IPrincipalStub : IPrincipal
{
    private IIdentity identityStub = new IIdentityStub();

    public IIdentity Identity
    {
        get { return identityStub; }
        set { identityStub = value; }
    }
}

public class IIdentityStub : IIdentity
{
    public string Name { get; set; } // BZZZT!!!
}

但是,Name接口中的IIdentity属性是只读的(IIDentity接口指定getter但不指定Name属性的setter。)

如果接口已将其定义为只读属性,如何在存根对象中设置Name属性以进行测试?

3 个答案:

答案 0 :(得分:3)

您正在使用C#的自动属性功能,但您应该使用手动路由并为该属性创建支持字段。一旦你有了一个支持字段,你可以在构造函数中设置它的值(或者将它设置为一个公共字段并在你拥有该对象后设置它,但这有点丑陋)。

public class IIdentityStub : IIdentity{
    private string _name;

    public IIdentityStub(string name){
        _name = name;
    }

    public string Name { get { return _name; } }
}

答案 1 :(得分:2)

我同意juharr - 使用模拟/隔离框架。我建议Moq

以下将打印“Robert”:

using System;
using System.Security.Principal;
using Moq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            var mockIdentity = new Mock<IIdentity>();
            var mockPrincipal = new Mock<IPrincipal>();

            mockIdentity.SetupGet(x => x.Name).Returns("Robert");
            mockPrincipal.SetupGet(x => x.Identity).Returns(mockIdentity.Object);

            IPrincipal myStub = mockPrincipal.Object;

            Console.WriteLine(myStub.Identity.Name);
        }
    }
}

编辑:但是,如果你想手工完成......

using System;
using System.Security.Principal;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main()
        {
            IIdentity identity =
                new IdentityStub
                    {
                        Name = "Robert",
                        AuthenticationType = "Kerberos",
                        IsAuthenticated = true
                    };

            IPrincipal principal = new PrincipalStub(identity);

            Console.WriteLine(principal.Identity.Name);  // Robert
            Console.WriteLine(principal.IsInRole(PrincipalStub.ValidRole));  // True
            Console.WriteLine(principal.IsInRole("OtherRole"));  // False
        }
    }

    public class PrincipalStub : IPrincipal
    {
        public const string ValidRole = "TestRole";

        public PrincipalStub(IIdentity identity)
        {
            Identity = identity;
        }

        public IIdentity Identity { get; private set; }

        public bool IsInRole(string role)
        {
            return role == ValidRole;
        }
    }

    public class IdentityStub : IIdentity
    {
        public string Name { get; set; }
        public string AuthenticationType { get; set; }
        public bool IsAuthenticated { get; set; }
    }
}

(以上是单元测试,只是使用一点依赖注入的手动存根的示例。)

答案 2 :(得分:1)

我建议使用像NMock

这样的模拟库