加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 模拟DataServiceQuery

发布时间:2020-12-15 19:55:40 所属栏目:asp.Net 来源:网络整理
导读:我如何模拟DataServiceQuery以进行单元测试? 详细信息如下: 想象一下ASP.NET MVC应用程序,其中控制器与ADO.NET DataService对话,封装了我们模型的存储(例如,我们将阅读Customers列表).通过对服务的引用,我们得到一个继承自DataServiceContext的生成类: na
我如何模拟DataServiceQuery以进行单元测试?

详细信息如下:
想象一下ASP.NET MVC应用程序,其中控制器与ADO.NET DataService对话,封装了我们模型的存储(例如,我们将阅读Customers列表).通过对服务的引用,我们得到一个继承自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 */
  }
}

财务主任可以是:

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实例的构造函数,以便我们可以在单元测试中使用mock:

[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需要实现相同的接口IMyDataContext:

namespace Sample.Services
{
  public interface IMyDataContext
  {
    DataServiceQuery<Customer> Customers { get; }
    /* and more */
  }
}

但是,当我们尝试实现MockContext类时,由于DataServiceQuery的性质,我们遇到了问题(很明显,我们在IMyDataContext接口中使用它只是因为这是我们在自动生成的MyDataContext中找到的数据类型我们开始的课程).如果我们试着写:

public class MockContext : IMyDataContext
{
  public IList<Customer> CustomersToReturn { set; private get; }

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

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

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

2~如果我使MockContext继承自DataServiceContext,并调用CreateQuery以获取要使用的DataService,则服务和查询必须绑定到有效的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试图获取模型中的元素数量,也会触发相同的错误.
提前致谢.

解决方法

[免责声明 – 我在Typemock工作]

您是否考虑过使用模拟框架?

您可以使用Typemock Isolator来创建DataServiceQuery的虚假实例:

var fake = Isolate.Fake.Instance<DataServiceQuery>();

您可以创建一个类似的假DataServiceContext并设置它的行为,而不是尝试继承它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读