Насмешливые члены IQueryable клиента WCF - PullRequest
2 голосов
/ 11 ноября 2010

У меня есть служба данных WCF, которая предоставляет интерфейсы:

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

Я хочу издеваться над сервисным клиентом для модульного тестирования. Я хотел бы написать тест как:

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

Но код завершается с ошибкой new DataServiceCollection<Contract>(blah) с сообщением об ошибке

SomeTests.MockContractsFromAccount: System.ArgumentException: не удалось определить DataServiceContext, к которому принадлежит экземпляр DataServiceCollection. DataServiceContext должен быть предоставлен в конструкторе DataServiceCollection или использоваться для создания объекта DataServiceQuery или QueryOperationResponse, который является источником элементов в DataServiceCollection

Кажется, это становится очень сложно. Есть ли способ, чтобы Visual Studio генерировала интерфейсы для Учетной записи и Контракта или чтобы accts.Contracts возвращал IQueryable<Contract> вместо DataServiceCollection<Contract>? Может быть, другое простое решение, чтобы издеваться над этим сервисом?


Для ясности, svcUtil.exe создает класс Account, который выглядит примерно так:

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 ]

7 голосов
/ 25 сентября 2012

Для тех, кто нашел этот вопрос поисковой системой.

Чтобы исключить исключение «DataServiceContext ... не удалось определить» при создании DataServiceCollection вручную, используйте перегруженный конструктор с параметром TrackingMode, установленным в значение «Нет».

т.е.,

new DataServiceCollection<Contract>(blah, TrackingMode.None)
0 голосов
/ 11 ноября 2010

Поскольку свойство Contracts имеет тип IEnumerable, вы можете создать любую перечисляемую коллекцию.

Итак, вместо

Contracts = new DataServiceCollection<Contract>(blah)

просто используйте

Contracts = new [] { blah }

Это гарантирует, что вы будете отключены в ваших поддельных объектах.

...