2
votes

I have a WCF data service that exposes interfaces:

public interface IAccountService
{
    IQueryable<Account> Accounts { get; }
    IQueryable<Contract> Contracts { get; }
}

[DataServiceKey("ID")]
public class Account
{
    public virtual Guid ID { get; set; }
    public virtual string AccountName { get; set; }
    public virtual string Address1 { get; set; }
    public virtual string Address2 { get; set; }
    public virtual string City { get; set; }
    public virtual string State { get; set; }
    public virtual string Zip { get; set; }
    public virtual string Phone { get; set; }
    public virtual string Fax { get; set; }
    public virtual string Status { get; set; }
    public virtual DateTime StartDate { get; set; }
    public virtual IEnumerable<Contract> Contracts { get; set; }
}

[DataServiceKey("ID")]
public class Contract 
{
    public virtual Guid ID { get; set; }
    public virtual string ContractCode { get; set; }
    public virtual string ContractName { get; set; }
    public virtual DateTime StartDate { get; set; }
    public virtual int UnitQty { get; set; }
    public virtual double UnitPrice { get; set; }
}

I want to mock the service client for unit testing. I would like to write a test like:

[Test]
public void MockContractsFromAccount()
{
    var acctSvc = new Mock<IAccountService>();
    var blah = new Contract[] { new Contract { ContractCode = "BLAH001", ContractName = "blah 1" }, 
        new Contract { ContractCode = "BLAH002", ContractName = "blah 2" } };
    var blee = new Contract[] { new Contract { ContractCode = "BLEE001", ContractName = "blee 1" } };
    var accts = new Account[] { new Account { AccountName = "blah", State = "WY", Contracts = new DataServiceCollection<Contract>(blah) }, 
        new Account { AccountName = "blee", State = "CO", Contracts = new DataServiceCollection<Contract>(blee) } };
    acctSvc.SetupGet(x => x.Accounts).Returns(accts.AsQueryable());

    var result = from x in acctSvc.Object.Accounts
                 where x.State == "CO"
                 select x;
    Assert.That(result, Has.Count.EqualTo(1));
    Assert.That(result.First().Contracts, Has.Count.EqualTo(2));
    Assert.That(result, Is.All.EquivalentTo(blah));
}

But the code fails at new DataServiceCollection<Contract>(blah) with the error message

SomeTests.MockContractsFromAccount: System.ArgumentException : The DataServiceContext to which the DataServiceCollection instance belongs could not be determined. The DataServiceContext must either be supplied in the DataServiceCollection constructor or be used to create the DataServiceQuery or QueryOperationResponse object that is the source of the items in the DataServiceCollection

This seems like it is getting very complicated. Is there a way to just have Visual Studio generate interfaces for Account & Contract or to have accts.Contracts return an IQueryable<Contract> instead of DataServiceCollection<Contract>? Maybe some other simple solution to mock this service?


For the sake of clarity, svcUtil.exe is generating an Account class that looks something like this:

public class Account 
{
    public Guid ID { get; set; }
    public string AccountName { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    public string Phone { get; set; }
    public string Fax { get; set; }
    public string Status { get; set; }
    public DateTime StartDate { get; set; }
    // It descends from IEnumerable<Contract>
    public DataServiceCollection<Contract> Contracts { get; set; }
}
2

2 Answers

7
votes

For those who found this question by a search engine.

To eliminate the "DataServiceContext ... could not be determined" exception while manually creating a DataServiceCollection, use the overloaded constructor with the TrackingMode parameter set to None.

I.e.,

new DataServiceCollection<Contract>(blah, TrackingMode.None)
-1
votes

As the Contracts property is of type IEnumerable, you can create any enumerable collection.

So, instead of

Contracts = new DataServiceCollection<Contract>(blah)

just use

Contracts = new [] { blah }

This will ensure you will be disconnected in your faked objects.