2

I want to mock(by moq) multiple QueryStrings in my unit testing class. Below is the piece of code :-

Adapter.MockQueryString("qs1", "1", _productController); 
Adapter.MockQueryString("qs2", "1", _productController); 

And below is my static function of Adapter class :-

   public static void MockQueryString(string querystringKey, string querystringValue, Controller controller)
   {
       var queryString1 = new NameValueCollection();
       queryString1.Add(querystringKey, querystringValue);

       // Set up a request
       var request = new Mock<System.Web.HttpRequestBase>();
       request.Setup(r => r.QueryString).Returns(queryString1);

       // Inject into the controller
       var controllerBase = new Mock<ControllerBase>();
       var contextBase = new Mock<System.Web.HttpContextBase>();
       contextBase.Setup(c => c.Request).Returns(request.Object);

       request.Setup(r => r.QueryString).Returns(queryString1);
       var controllerContext = new ControllerContext(contextBase.Object, new System.Web.Routing.RouteData(), controllerBase.Object);
       controller.ControllerContext = controllerContext;
   }

Problem is its only mocking the last query string (qs2).And giving null for qs1.How we can mock multiple query strings ?

Pawan
  • 2,150
  • 11
  • 45
  • 73

2 Answers2

0

Moq has SetupSequence, which allows you to return different results after each invocation of the Mock

request.SetupSequence(r => r.QueryString)
       .Returns(queryString1)
       .Returns(queryString2);

You may have to adjust your setup to accept a collection

Edit

In the general case, you may be better off using Setup with a stateful mechanism, e.g. accessing an iterator via a closure:

public static void MockQueryString(IEnumerable<Tuple<string, string>> qstringTuples, 
                                   Controller controller)
{
    // Convert collection to IEnum<NameValueCollection>
    var queryStrings = qstringTuples
        .Select(_ => new NameValueCollection {{_.Item1, _.Item2}})
        .ToList();
    // Set up a request
    var request = new Mock<System.Web.HttpRequestBase>();
    var queryStringIterator = queryStrings.GetEnumerator();
    request.SetupGet(r => r.QueryString)
           .Returns(() =>
                        {
                            queryStringIterator.MoveNext();
                            return queryStringIterator.Current;
                        });
Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • @SturartLC,can you suggest the whole process ? – Pawan Apr 30 '14 at 06:32
  • I'm not 100% of your requirement, but the above approach allows you to preset N values to be returned from your Mock to your SUT. `SetupSequence` would work best in a simple Unit Test with a few calls to `QueryString`, but since you seem to have abstracted a framework for setup, you may want to do the general sense of sequentially returning each of a collection of values on subsequent calls. Note an earlier error in my setup -> QueryString is a property, not a method. – StuartLC Apr 30 '14 at 06:38
0

The problem is that you're setting up a property to return an object (the NameValueCollection with qs1), and then setting it up to return a different object (a different NameValueCollection with qs2). The second SetUp replaces the first one, which is why you always get the qs2 string.

Build the NameValueCollection outside of MockQueryString and pass that in, so you set up the property return value only once:

public static void MockQueryStrings(NameValueCollection queryStrings, Controller controller)
{
    // Set up a request
    var request = new Mock<System.Web.HttpRequestBase>();
    request.Setup(r => r.QueryString).Returns(queryStrings);

    ... etc
}

Then invoke MockQueryStrings once:

var queryStrings = new NameValueCollection();
queryStrings.Add("qs1", "1");
queryStrings.Add("qs2", "2");
Adapter.MockQueryStrings(queryStrings, _productController); 
Patrick Quirk
  • 23,334
  • 2
  • 57
  • 88