Moq Examples for Lecture

First, something to mock. Here's an interface with some methods we can use.

namespace Standups.Models.Example
{
    public class ExampleAccount
    {
        public int AccountNumber { get; set; }
        public bool IsOpen { get; set; } = false;
    }

    // An example repository for mocking example
    public interface IAccountRepository
    {
        // Simple property
        string Name { get; set; }

        // Parameterless method
        bool IsValid();

        // Primitive type parameter 
        int GetBaseAccountNumber(int num);

        // Object type parameter
        bool Update(ExampleAccount ea);

        // Object type returned
        ExampleAccount GetNewAccount();
    }
}

And here are some Moq examples for how you can mock different kinds of methods. Yes, we're not actually mocking any useful behavior here -- this is just to show syntax and general organization.

using System;
using Moq;
using NUnit.Framework;
using Standups.Models.Example;

namespace Tests.Examples
{
    [TestFixture]
    public class ExampleTests
    {
        [Test]
        public void Test_A_Property()
        {
            // Arrange
            string expected = "George";
            Mock<IAccountRepository> mock = new Mock<IAccountRepository>();
            mock.Setup(m => m.Name)
                .Returns(expected);

            // Act 
            IAccountRepository ar = mock.Object;
            string name = ar.Name;
            // in reality, do something useful with this IAccountRepository instance

            // Assert
            Assert.That(name, Is.EqualTo(expected));
        }

        [Test]
        public void Test_Parameterless_Method()
        {
            Mock<IAccountRepository> mock = new Mock<IAccountRepository>();
            mock.Setup(m => m.IsValid())
                .Returns(true);

            IAccountRepository ar = mock.Object;

            Assert.That(ar.IsValid(), Is.True);
        }

        [Test]
        public void Test_SimpleParameter_Method()
        {
            Mock<IAccountRepository> mock = new Mock<IAccountRepository>();
            mock.Setup(m => m.GetBaseAccountNumber(5))
                .Returns(100);

            IAccountRepository ar = mock.Object;

            Assert.That(ar.GetBaseAccountNumber(5), Is.EqualTo(100));
        }

        [Test]
        public void Test_SimpleParameter_Method_WithAny()
        {
            Mock<IAccountRepository> mock = new Mock<IAccountRepository>();
            mock.Setup(m => m.GetBaseAccountNumber(It.IsAny<int>()))
                .Returns(100);
          
            IAccountRepository ar = mock.Object;

            Assert.That(ar.GetBaseAccountNumber(88), Is.EqualTo(100));
        }

        [Test]
        public void Test_Method_Taking_An_Object()
        {
            ExampleAccount ea = new ExampleAccount() { AccountNumber = 12345 };
            Mock<IAccountRepository> mock = new Mock<IAccountRepository>();
            mock.Setup(m => m.Update(It.IsAny<ExampleAccount>()))
                .Returns(true);

            IAccountRepository ar = mock.Object;

            Assert.That(ar.Update(ea), Is.True);
        }

        [Test]
        public void Test_Method_Returning_An_Object()
        {
            Mock<IAccountRepository> mock = new Mock<IAccountRepository>();
            mock.Setup(m => m.GetNewAccount())
                .Returns(
                    new ExampleAccount { AccountNumber = 42, IsOpen = true}
                 );

            IAccountRepository ar = mock.Object;

            Assert.That(ar.GetNewAccount().IsOpen, Is.True);
        }
    }
}

Here's a starting example for mocking part of a repository. Note: there are plenty of examples out there you can find that show mocking the usual CRUD functionality.

namespace Standups.Models.Abstract
{
    public interface ISUPRepository : IDisposable
    {
        IEnumerable<SUPUser> SUPUsers { get; }
    }
}
namespace Standups.Models.Concrete
{
    public class EFSUPRepository : ISUPRepository
    {
        private SUPContext db = new SUPContext();

        public IEnumerable<SUPUser> SUPUsers
        {
            get { return db.SUPUsers; }
        }

        public void Dispose()
        {
            db.Dispose();
        }
    }
}

And a couple tests using it.

namespace Tests.TestControllers
{
    [TestFixture]
    public class TestHome
    {
        private Mock<ISUPRepository> mock;

        [SetUp]
        public void SetupUserMock()
        {
            SUPGroup[] groups = new SUPGroup[] {
                    new SUPGroup { ID = 1, Name = "Group 1" },
                    new SUPGroup { ID = 2, Name = "Group 2" }
                    };

            mock = new Mock<ISUPRepository>();
            mock.Setup(m => m.SUPUsers)
                .Returns(
                new SUPUser[]
                {
                    new SUPUser {ID = 1, FirstName = "Bob", LastName = "Roberts", SUPGroupID = 1, SUPGroup = groups[0], ASPNetIdentityID = "id001"},
                    new SUPUser {ID = 2, FirstName = "Julie", LastName = "Juliet", SUPGroupID = 1, SUPGroup = groups[0], ASPNetIdentityID = "id002"},
                    new SUPUser {ID = 3, FirstName = "Rick", LastName = "Rickard", SUPGroupID = null, SUPGroup = null, ASPNetIdentityID = "id003"},
                    new SUPUser {ID = 4, FirstName = "Sue", LastName = "Suarez", SUPGroupID = 2, SUPGroup = groups[1], ASPNetIdentityID = "id004"},
                    new SUPUser {ID = 5, FirstName = "John", LastName = "Johanson", SUPGroupID = null, SUPGroup = null, ASPNetIdentityID = "id005"}
                });
        }

        [Test]
        public void UserNeedsGroup()
        {
            // Arrange
            HomeController controller = new HomeController(mock.Object);
            // Act
            SUPUser u = mock.Object.SUPUsers.ElementAt(2);
            // Assert
            Assert.That(controller.SUPUserNeedsGroupSet(u), Is.True);
        }

        [Test]
        public void UserDoesNotNeedGroup()
        {
            // Arrange
            HomeController controller = new HomeController(mock.Object);
            // Act
            SUPUser u = mock.Object.SUPUsers.ElementAt(0);
            // Assert
            Assert.That(controller.SUPUserNeedsGroupSet(u), Is.False);
        }
        
        // This method mocks enough of Identity to be able to test the
        // view produced by this controller action method
        
        
        public ControllerContext GetMockControllerContext(SUPUser u)
        {
            // mock parts of Identity:
            // Using parts of http://stackoverflow.com/questions/22762338/how-do-i-mock-user-identity-getuserid    and
            // http://stackoverflow.com/questions/758066/how-to-mock-controller-user-using-moq

            // mock an Identity with a known id
            var identity = new GenericIdentity("TestUsername");
            identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", u.ASPNetIdentityID));
            //   This line above is fragile in that is assumes ASP.NET Identity looks for exactly this string for the claim key string.
            //   It will fail if not an exact match.  If it fails then the lookup fails and GetUserId() returns null, meaning no User
            //   is found.  Look at the source code for: IdentityExtensions.GetUserId()

            // mock an IPrincipal that uses the mock identity
            Mock<IPrincipal> mockIPrincipal = new Mock<IPrincipal>();
            mockIPrincipal.Setup(p => p.Identity)
                          .Returns(identity);

            // mock a controller context for the controller to use
            Mock<ControllerContext> mockControllerContext = new Mock<ControllerContext>();
            mockControllerContext.Setup(p => p.HttpContext.User)
                                 .Returns(mockIPrincipal.Object);

            return mockControllerContext.Object;
        }

        [Test]
        public void AuthenticatedUserWhoNeedsGroup_ShouldSetViewData()
        {
            HomeController controller = new HomeController(mock.Object);

            // user for this test, who needs to have a group set
            SUPUser u = mock.Object.SUPUsers.ElementAt(2);

            // Use the context, which will return the given identity id
            controller.ControllerContext = GetMockControllerContext(u);

            // Generate enough of the view to hold the ViewBag data we set there
            ViewResult index = (ViewResult) controller.Index();

            // See if it got set
            Assert.That(index.ViewData["NeedsGroup"], Is.True);
        }

        // NOTE: need to refactor this duplicated code into a common method
        [Test]
        public void AuthenticatedUserWhoNeedsNOGroup_ShouldNOTSetViewData()
        {
            HomeController controller = new HomeController(mock.Object);
            // user for this test who already has a group set
            SUPUser u = mock.Object.SUPUsers.ElementAt(1);

            // Use the context, which will return the given identity id
            controller.ControllerContext = GetMockControllerContext(u);

            // Generate enough of the view to hold the ViewBag data we set there
            ViewResult index = (ViewResult)controller.Index();

            // See if it got set
            Assert.That(index.ViewData["NeedsGroup"], Is.False);
        }
    }
}