【问题标题】:How to mock multiple query strings?如何模拟多个查询字符串?
【发布时间】:2014-06-16 07:26:36
【问题描述】:

我想在我的单元测试类中模拟(按起订量)多个 QueryString。 下面是一段代码:-

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

下面是我的适配器类的静态函数:-

   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;
   }

问题是它唯一模拟了最后一个查询字符串(qs2)。并且为 qs1 赋予 null。我们如何模拟多个查询字符串?

【问题讨论】:

    标签: c# unit-testing mocking moq request.querystring


    【解决方案1】:

    Moq 有SetupSequence,它允许您在每次调用 Mock 后返回不同的结果

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

    您可能需要调整设置以接受收藏

    编辑

    在一般情况下,您最好使用带有状态机制的Setup,例如通过闭包访问迭代器:

    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;
                            });
    

    【讨论】:

    • @SturartLC,你能建议整个过程吗?
    • 我不是 100% 满足您的要求,但上述方法允许您预设 N 个值从您的 Mock 返回到您的 SUT。 SetupSequence 在简单的单元测试中效果最好,只需调用几次QueryString,但由于您似乎已经抽象了一个设置框架,您可能想要按顺序返回每个值集合的一般意义后续调用。请注意我的设置中的早期错误 -> QueryString 是属性,而不是方法。
    【解决方案2】:

    问题是您正在设置一个属性以返回一个对象(NameValueCollectionqs1),然后将其设置为返回一个不同的对象(一个不同的 NameValueCollectionqs2) .第二个SetUp 替换了第一个,这就是为什么你总是得到qs2 字符串。

    MockQueryString 之外构建NameValueCollection 并将其传入,因此您只需设置一次属性返回值:

    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
    }
    

    然后调用一次MockQueryStrings

    var queryStrings = new NameValueCollection();
    queryStrings.Add("qs1", "1");
    queryStrings.Add("qs2", "2");
    Adapter.MockQueryStrings(queryStrings, _productController); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-18
      • 2022-08-04
      • 1970-01-01
      • 1970-01-01
      • 2017-09-19
      • 1970-01-01
      • 2016-09-01
      相关资源
      最近更新 更多