Параметры для модульного тестирования типа возврата, который я не могу легко создать - PullRequest
2 голосов
/ 18 декабря 2011

Мне нужно провести модульное тестирование метода, который возвращает тип, который я не могу легко подделать или создать.Тип реализует IQueryable<T>, который я изначально думал, что мог бы использовать в своих интересах, но я не понимаю, как на этом этапе.

Например:

public sealed class MyTrickyClass<T> : IQueryable<T>
{
    ...
}

public MyTrickyClass<T> GetData()
{
    return repository.GetAllData();
}

и мой модульный тест

[Test Method]
public void CanGetData()
{
    var data = (new List<Record>() { new Record() }).AsQueryable();
    var mockRepository = new Mock<IRepository<Record>>();
    mockRepository.Setup(s => s.GetAllData()).Returns(data);

    MyService service = new MyService(mockRepository.Object);
    var result = service.GetData();

    Assert.IsNotNull(result);

}

Это не скомпилируется, потому что тип возвращаемого значения GetAllData () - MyTrickyClass<T>.Если я попытаюсь привести data к типу MyTrickyClass<Record>, приведение не удастся.

Все это имеет смысл, но это заставляет меня задуматься, каково правильное решение.Какие есть обходные пути для такой ситуации?Возможно, я смогу изменить MyTrickyClass, но в идеале я хотел бы найти решение, которое оставляет его в покое.

Ответы [ 2 ]

2 голосов
/ 26 декабря 2011

Ваша data переменная в тесте является IQueryable<Record>, а не MyTrickyClass<Record>.

Вот несколько возможностей исправить это:

  • Измените data в тесте на MyTrickyClass<Record> (хотя я предполагаю, что если бы это было возможно, вы бы это уже сделали)
  • Сделайте MyTrickyClass проще в построении, затем сделайте выше
  • Измените интерфейс IRepository, чтобы он возвращал IQueryable вместо MyTrickyClass (что лучше всего, если все, что ему нужно - это IQueryable в любом случае)
  • Обернуть репозиторий в слой, который позволяет вам также обернуть возвращаемое значение. Это еще один уровень абстракции, но если вы обнаружите, что не можете изменить хранилище или MyTrickyClass, то, возможно, вы все равно захотите изолировать себя от него
  • Как подсказал @Erik Dietrich, вы можете заставить MyTrickyClass реализовать интерфейс. Однако вы все равно не сможете создавать данные, используя IQueryable, поскольку приведение не будет выполнено. Однако вместо этого вы можете создать макет ITrickyClass или создать небольшой класс-заглушку, реализующий интерфейс (если MyTrickyClass является объектом домена, вы, вероятно, будете его использовать во многих местах, так что может быть полезнее заглушка).
2 голосов
/ 18 декабря 2011

Вы могли бы MyTrickyClass<T> реализовать интерфейс ITrickyClass<T>, который наследуется от IQueryable<T>. Это кажется минимально инвазивным для самого вашего класса, и у вас будет хороший шов для насмешек.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...