Setup on the same method using MOQ

Someone asked me about this today and I thought of it is a useful tip to write a small post. See the below code. If you know how to setup the same method in such a way that it would not override during the test execution, you can stop reading the rest of the post. If not please see the below example.

    public class SomeClass
    {
        private readonly ISomeInterface _someInterface;

        public SomeClass(ISomeInterface someInterface){
            _someInterface = someInterface;
        }

        public string SomeMethod()
        {
            string str1 = "str1";
            string str2 = "str2";
            
           var r1 = _someInterface.DoSomething(str1, str2);
            var r2 = _someInterface.DoSomething(string.Empty, string.Empty);
            
            return "something";
        }
    }

Notice that the same method call twice with different parameters. In our Unit Test, if we were to stub these two methods, the second/last setup method overrides the first one. In other words both r1 and r2 has the value of “bar”. This is not what we expect as we want setup methods to behave differently and return different values for r1 and r2.

Couple of ways you can achieve this with Moq.

a. Using It.Is

You can specify a predicate that matches a specified criteria.

[TestMethod]
public void TestMethod3()
{
       var stub = new Mock<ISomeInterface>();
        stub.Setup(x => x.DoSomething(It.Is<string>
                     (s => !string.IsNullOrEmpty(s)), It.Is<string>
                     (s => !string.IsNullOrEmpty(s)))).Returns("foo");
        stub.Setup(x => x.DoSomething(It.Is<string>
                     (s => string.IsNullOrEmpty(s)), It.Is<string>
                     (s => string.IsNullOrEmpty(s)))).Returns("bar");
            
        var sut = new SomeClass(stub.Object);
        var r = sut.SomeMethod();
     }

b. This is the one that I like most as it only needs one setup and slightly quicker
Provide the delegate on the “Returns” that match the criteria.

[TestMethod]
 public void TestMethod2()
 {
       var stub = new Mock<ISomeInterface>();
       stub.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<string>()))
                .Returns<string, string>((x, y) => {
                     if (x != string.Empty && y != string.Empty){ return "foo";}
                     if (x == string.Empty && y == string.Empty){ return "bar";}         
                     return string.Empty;
           });

       var sut = new SomeClass(stub.Object);

       var r = sut.SomeMethod();

   }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s