Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you create a unit-testing stub for an interface containing a read-only member?

I am writing some unit tests for an extension method I have written on IPrincipal. To assist, I have created a couple of helper classes (some code for not-implemented members of the interfaces has been omitted for brevity):

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!!!
}

However, the Name property in the IIdentity interface is read-only (the IIDentity interface specifies a getter but not a setter for the Name property).

How can I set the Name property in my stub object for testing purposes if the interface has defined it as a read-only property?

like image 496
Robert Harvey Avatar asked Mar 29 '10 18:03

Robert Harvey


People also ask

How do you stub in unit testing?

To use stubs, you have to write your component so that it uses only interfaces, not classes, to refer to other parts of the application. This is a good design practice because it makes changes in one part less likely to require changes in another. For testing, it allows you to substitute a stub for a real component.

How do you test an interface in unit testing?

To test an interface with common tests regardless of implementation, you can use an abstract test case, and then create concrete instances of the test case for each implementation of the interface.

What is stub in unit testing Java?

A stub is a fake class that comes with preprogrammed return values. It's injected into the class under test to give you absolute control over what's being tested as input. A typical stub is a database connection that allows you to mimic any scenario without having a real database.


2 Answers

You're using the auto-properties feature of C# but instead you should go the manual route and create a backing field for the property. Once you have a backing field you can set its value in the constructor (or make it a public field and set it after you have the object, but this is a little uglier).

public class IIdentityStub : IIdentity{
    private string _name;

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

    public string Name { get { return _name; } }
}
like image 177
Jason Punyon Avatar answered Sep 26 '22 19:09

Jason Punyon


I agree with juharr - use a mocking/isolation framework. I'd recommend Moq.

The following will print "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);
        }
    }
}

EDIT: But if you want to do it by hand...

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; }
    }
}

(The above is not a unit test, just an example of hand-rolled stubs using a bit of dependency injection.)

like image 23
TrueWill Avatar answered Sep 26 '22 19:09

TrueWill