我怎么可以嘲笑一个DataServiceQuery单元测试的目的是什么?

长详细信息如下:想象一下一个ASP.NET 软应用程序,在那里控制器会谈到一个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 */
  }
}

控制器可以是:

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需要实现相同的接口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 { /* ??? */ } }
}

在客户吸气我们想要实例DataServiceQuery实例,其中填充的客户在CustomersToReturn,并返回。问题是我运行为:

1~ DataServiceQuery没有公共构造方法;实例之一你应该打电话给CreateQuery在DataServiceContext;看看 MSDN

2~ 如果我做的MockContext继承DataServiceContext,并呼吁CreateQuery获得DataServiceQuery使用、服务和查询有被绑到一个有效的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;
      }
    }
  }
}

然后,在该单元的测试,我们得到一个错误的线标示为行一,因为 http://www.contoso.com 不主持我们的服务。同样的错误是触发的,即使行的一个试图获得数量元素中的模型。在此先感谢。

有帮助吗?

解决方案

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

你有没有用讽刺的框架考虑?

可以使用Typemock隔离器来创建化DataServiceQuery的假实例:

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

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

其他提示

我解决了这个通过创建一个接口 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 在它的构造,然后代表所有的功能以查询。同样地, MockDataServiceQuery 需要一个 IQueryable 和代表的一切它可以查询。

为模拟 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;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top