我想在我的单元测试类中模拟(通过moq(多个QueryStrings。下面是一段代码:-
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。我们如何模拟多个查询字符串?
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;
});
问题是,您要设置一个属性以返回一个对象(NameValueCollection
和qs1
(,然后设置它以返回不同的对象(不同的NameValueCollection
和qs2
(。第二个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);