Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practice For Mocking Repository Pattern

Tags:

moq

I'm starting out with IoC / Mocking and am looking to make sure I'm using 'best practice' for my repositories.

I'm setting up interfaces for my repositories. The concrete implementations will point to SQL, whilst testing will use Moq to generate "fakes". I notice that I'm using Moq's callback feature a lot. In this article, the author states.

since Moq provides functionality in both of these areas for most of what you would want to do, there isn’t really too many different points at which you would need these tools. In fact, if you think you need to use “Callback” you should probably look a little harder to see if Moq can do what you want to do automatically.

I've had a look and can't see any other way to implement what I need - namely a 'fake' repository. Can someone please advise if there's something that I'm missing here? Is there any way to achieve this without the callback?

public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        // Arrange
        var mock = ContactRepositoryFake();

        // Act
        mock.Object.AddContact(new Contact() { Name = "bill" });
        mock.Object.AddContact(new Contact() { Name = "jane" });

        // Assert
        Assert.IsTrue(mock.Object.AllContacts.Count() == 2);
    }

    public Mock<IContactRepository> ContactRepositoryFake()
    {
        var _allContacts = new List<Contact>();
        var mock = new Mock<IContactRepository>();
        mock.Setup(x=>x.AddContact(It.IsAny<Contact>()))
            .Callback((Contact c) =>
                {
                    _allContacts.Add(c);
                });
        mock.Setup(x => x.AllContacts).Returns(_allContacts);
        return mock;

    }
}

public interface IContactRepository
{
    void AddContact(Contact contact);
    IEnumerable<Contact> AllContacts { get; }
}

public class Contact
{
    public string Name { get; set; }
}

Thank you very much in advance! Any other advise welcome :-)

Z

like image 761
Damien Sawyer Avatar asked Jun 08 '11 06:06

Damien Sawyer


2 Answers

I personally do not see an issue with the way you are doing this. What I see is that you want to Mock and not Stub you repository. Which means you want it to "record" and return data back during the test. In this case Callback is useful and really the only way to do this.

As for the comment if you are dealing with Stubbing more than mocking then Callback would be rarely be used. the article imo is a bit to general and doesn't fully see the power of the Callback.

like image 185
aqwert Avatar answered Oct 22 '22 16:10

aqwert


You could just setup the following:

mock.Setup(x => x.AllContacts).Returns(GetExpectedContactList());

and have a helper function which returns a List of Contacts:

private static List<Contact> GetExpectedContactList() 
{
....
}

And have different Helper methods to return specific data scenarios.

like image 23
Ciaran Avatar answered Oct 22 '22 14:10

Ciaran