gpt4 book ai didi

asp.net-mvc - 模拟 DataServiceQuery

转载 作者:行者123 更新时间:2023-12-04 20:25:35 25 4
gpt4 key购买 nike

如何模拟 DataServiceQuery 以进行单元测试?

详细信息如下:
想象一个 ASP.NET MVC 应用程序,其中 Controller 与封装模型存储的 ADO.NET DataService 通信(例如,我们将读取客户列表)。通过对服务的引用,我们得到一个继承自 DataServiceContext 的生成类:

namespace Sample.Services
{
public partial class MyDataContext : global::System.Data.Services.Client.DataServiceContext
{
public MyDataContext(global::System.Uri serviceRoot) : base(serviceRoot) { /* ... */ }

public global::System.Data.Services.Client.DataServiceQuery<Customer> Customers
{
get
{
if((this._Customers==null))
{
this._Customers = base.CreateQuery<Customer>("Customers");
}
return this._Customers;
}
}
/* and many more members */
}
}

Controller 可以是:
namespace Sample.Controllers
{
public class CustomerController : Controller
{
private IMyDataContext context;

public CustomerController(IMyDataContext context)
{
this.context=context;
}

public ActionResult Index() { return View(context.Customers); }
}
}

如您所见,我使用了一个接受 IMyDataContext 实例的构造函数,以便我们可以在单元测试中使用模拟:
[TestFixture]
public class TestCustomerController
{
[Test]
public void Test_Index()
{
MockContext mockContext = new MockContext();
CustomerController controller = new CustomerController(mockContext);

var customersToReturn = new List<Customer>
{
new Customer{ Id=1, Name="Fred" },
new Customer{ Id=2, Name="Wilma" }
};
mockContext.CustomersToReturn = customersToReturn;

var result = controller.Index() as ViewResult;

var models = result.ViewData.Model;

//Now we have to compare the Customers in models with those in customersToReturn,
//Maybe by loopping over them?
foreach(Customer c in models) //*** LINE A ***
{
//TODO: compare with the Customer in the same position from customersToreturn
}
}
}

MockContext和MyDataContext需要实现相同的接口(interface)IMyDataContext:
namespace Sample.Services
{
public interface IMyDataContext
{
DataServiceQuery<Customer> Customers { get; }
/* and more */
}
}

但是,当我们尝试实现 MockContext 类时,由于 DataServiceQuery 的性质,我们遇到了问题(需要明确的是,我们在 IMyDataContext 接口(interface)中使用它只是因为这是我们在自动生成的 MyDataContext 中找到的数据类型我们开始的类(class))。如果我们尝试写:
public class MockContext : IMyDataContext
{
public IList<Customer> CustomersToReturn { set; private get; }

public DataServiceQuery<Customer> Customers { get { /* ??? */ } }
}

在Customers getter 中,我们希望实例化一个DataServiceQuery 实例,用CustomersToReturn 中的Customers 填充它,然后返回它。我遇到的问题:

1~ DataServiceQuery 没有公共(public)构造函数;要实例化一个,您应该在 DataServiceContext 上调用 CreateQuery;见 MSDN

2~ 如果我让 MockContext 也从 DataServiceContext 继承,并调用 CreateQuery 以获取要使用的 DataServiceQuery,则服务和查询必须绑定(bind)到有效的 URI,并且当我尝试迭代或访问查询中的对象时,它将尝试并针对该 URI 执行。换句话说,如果我这样更改 MockContext :
namespace Sample.Tests.Controllers.Mocks
{
public class MockContext : DataServiceContext, IMyDataContext
{
public MockContext() :base(new Uri("http://www.contoso.com")) { }

public IList<Customer> CustomersToReturn { set; private get; }

public DataServiceQuery<Customer> Customers
{
get
{
var query = CreateQuery<Customer>("Customers");
query.Concat(CustomersToReturn.AsEnumerable<Customer>());
return query;
}
}
}
}

然后,在单元测试中,我们在标记为 LINE A 的行上得到一个错误,因为 http://www.contoso.com不托管我们的服务。即使 LINE A 尝试获取模型中的元素数量,也会触发相同的错误。
提前致谢。

最佳答案

我通过创建接口(interface) IDataServiceQuery 解决了这个问题有两种实现:

  • DataServiceQueryWrapper
  • MockDataServiceQuery

  • 然后我使用 IDataServiceQuery我以前会使用 DataServiceQuery 的任何地方.
    public interface IDataServiceQuery<TElement> : IQueryable<TElement>, IEnumerable<TElement>, IQueryable, IEnumerable
    {
    IDataServiceQuery<TElement> Expand(string path);

    IDataServiceQuery<TElement> IncludeTotalCount();

    IDataServiceQuery<TElement> AddQueryOption(string name, object value);
    }
    DataServiceQueryWrapper需要 DataServiceQuery在它的构造函数中,然后将所有功能委托(delegate)给传入的查询。类似地, MockDataServiceQuery需要 IQueryable并将它所能做的一切委托(delegate)给查询。

    模拟 IDataServiceQuery方法,我目前只返回 this ,尽管如果您愿意,您可以做一些事情来模拟功能。

    例如:
    // (in DataServiceQueryWrapper.cs)
    public IDataServiceQuery<TElement> Expand(string path)
    {
    return new DataServiceQueryWrapper<TElement>(_query.Expand(path));
    }
    // (in MockDataServiceQuery.cs)
    public IDataServiceQuery<TElement> Expand(string path)
    {
    return this;
    }

    关于asp.net-mvc - 模拟 DataServiceQuery<TElement>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1439190/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com