Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return different values for different input in mock?

Tags:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var o1 = new XmlDocument();
        var o2 = new XmlDocument();

        var mock = new Mock<ITestInterface>();
        mock.Setup(m => m.TestMethod(o1)).Returns(1);
        mock.Setup(m => m.TestMethod(o2)).Returns(2);

        Assert.AreEqual(1, mock.Object.TestMethod(o1));
        Assert.AreEqual(2, mock.Object.TestMethod(o2));
    }
}

public interface ITestInterface
{
    int TestMethod(object input);
}

Why mock always returns second value? If I switched XmlDocument to anything else (object, StringBuilder etc) it would work as expected.

like image 565
Kamil Avatar asked Sep 10 '18 18:09

Kamil


2 Answers

I would have assumed it would work as you expected as well, but I also get the same results. However if you instead do your setup as below, it will work as you want it to.

mock.Setup(m => m.TestMethod(It.Is<XmlDocument>(y => ReferenceEquals(o1, y)))).Returns(1);
mock.Setup(m => m.TestMethod(It.Is<XmlDocument>(y => ReferenceEquals(o2, y)))).Returns(2);

Something else I noticed as I tested further is that if you set the InnerXml, everything works as you originally setup.

var doc1 = new XmlDocument { InnerXml = "<root1 />" };
var doc2 = new XmlDocument { InnerXml = "<root2 />" };;
mock.Setup(x => x.TestMethod(doc1)).Returns(1);
mock.Setup(x => x.TestMethod(doc2)).Returns(2);

Console.WriteLine($"{mock.Object.TestMethod(doc1)}");
Console.WriteLine($"{mock.Object.TestMethod(doc2)}");

It even works if you set both InnerXml values to be identical strings. Its really a mystery and I've been unable to explain it.

like image 96
Andy Avatar answered Oct 11 '22 14:10

Andy


I ran your code and experience the same issue. Running your code exactly how you posted fails on the first Assert with Message: Assert.AreEqual failed. Expected:<1>. Actual:<2>.. When I change o1 and o2 to object instead of XmlDocument it worked as expected.

Strangely enough, changing the 2 setup lines to the following will cause it to produce correct results:

mock.Setup(m => m.TestMethod(It.Is<XmlDocument>(x => x == o1))).Returns(1);
mock.Setup(m => m.TestMethod(It.Is<XmlDocument>(x => x == o2))).Returns(2);

This is strange because I believe that your 2 setup lines are supposed to behave exactly like mine, yet mine work correctly in this case while yours don't. I assume that there is a difference which I'm not aware of or that there is a bug with Moq that causes this.

like image 44
Aaron T Avatar answered Oct 11 '22 13:10

Aaron T