Mocking DataServiceQuery <TElement>

How can I make fun of DataServiceQuery for unit testing purposes?

Long details follow: Imagine an ASP.NET MVC application in which the controller discusses with ADO.NET DataService, which encapsulates the storage of our models (for example, we will read the list of clients). With a reference to the service, we get the generated class inheriting from the 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 */
  }
}

The controller may be:

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

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

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

As you can see, I used a constructor that takes an instance of IMyDataContext so that we can use the layout in our unit test:

[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 and MyDataContext must implement the same IMyDataContext interface:

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 { /* ??? */ } }
}

Getters DataServiceQuery, CustomerToReturn . , :

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

unit test , LINE A, http://www.contoso.com . , LINE A . .

+5
2

[ - Typemock]

?

Typemock Isolator DataServiceQuery:

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

DataServiceContext , .

0

, 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 , , .

mock 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;
}
+4

All Articles