简体   繁体   中英

Mocking a visitor object using Moq

I've written a piece of code that is responsible for creating an Issue.It uses a visitor pattern to set the Issue assignee. Here's the code :

public Issue CreateIssue(IssueType type, string subject, string description, Priority priority, string ownerId)
        {
            var issue = new Issue
            {
                ...
            };
            IssueManagerContext.Current.IssueAssignmentMethodResolver(type).Visit(issue);
            ...
            return issue;
        }

I would like to test the functionality of this code thus somehow I need to mock the behavior of a visitor. After studying different Mock libraries I decided to use Moq . But I don't know how should I build a mock object that gets an argument from my code instead of hard coding it as it's shown in the quick start guide.

Here's what I have done so far :

var visitor = new Mock<IIssueVisitor>();
visitor.Setup(x => x.Visit(null));

You can only match a specific instance of an object if the test has the same reference as the SUT. The problem in your scenario is that your SUT creates the instance issue , and returns it at the end of the method. Your test cannot access it while the method is executing , which precludes your mock object from being able to match it.

You can configure your mock object to match any Issue instance with the following syntax:

    visitor.Setup(x => x.Visit(It.IsAny<Issue>()));

You can also configure the mock to conditionally match an Issue instance:

    // Matches any instance of Issue that has an ID of 42
    visitor.Setup(x => x.Visit(It.Is<Issue>(theIssue => theIssue.ID == 42)));

If you want to match the reference of a specific instance of Issue , then you'll have to move the instantiation logic into some kind of abstraction (eg, a factory) of which your test could provide a fake implementation. For example:

    // In SUT
    var issue = issueFactory.CreateIssue();
    ...

    // In test
    var stubIssue = new Issue{ ... };
    var issueFactory = new Mock<IIssueFactory>();
    var visitor = new Mock<IIssueVisitor>();
    ...        
    issueFactory.Setup(factory => factory.CreateIssue())
        .Returns(stubIssue);

    visitor.Setup(x => x.Visit(stubIssue));

Use the following syntax:

interface IFoo
{
    int Bar(string baz);
}

var mock = new Mock<IFoo>();
mock.Setup(x => x.Bar(It.IsAny<string>()))
    .Returns((string baz) => 42 /* Here baz contains the value your code provided */);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM