Модульное тестирование Linq 2 Sql лениво-загруженных свойств

Допустим, у меня есть таблица «Клиенты» и таблица «Заказы» с привязкой «один ко многим» (один клиент может иметь несколько заказов). Если у меня есть какой-то код, который я хотел бы выполнить модульным тестом, который получает доступ к заказам конкретного клиента через ленивую загрузку (например, вызов customer.Orders), как мне смоделировать / заглушить этот вызов, чтобы он не попал в базу данных?

Редактировать:

Чтобы быть более понятным, давайте использовать более конкретный пример. Допустим, я хочу вернуть все заказы для конкретного клиента. Я мог бы написать это так, используя автоматически сгенерированные свойства отложенной загрузки, которые предоставляет Linq 2 Sql:

Customer customer = customerRepository.GetCustomerById(customerId);

return customer.Orders;

Тем не менее, модульное тестирование это немного сложно. Я могу смоделировать вызов GetCustomerById, но не могу (насколько я могу судить) смоделировать вызов Orders. Единственный способ, которым я могу подумать о модульном тестировании, это либо а) подключиться к базе данных (что замедлит мои тесты и будет хрупким), либо б) не использовать свойства отложенной загрузки.

Не используя свойства отложенной загрузки, я, вероятно, переписал бы вышеизложенное как это:

return orderRepository.GetOrdersByCustomerId(customerId);

Это определенно работает, но неудобно полностью игнорировать свойства отложенной загрузки просто для модульного тестирования.

13.10.2009 07:59:31
1 ОТВЕТ
РЕШЕНИЕ

В качестве общего ответа на ваш вопрос, вы заглушаете этот вызов так же, как заглушаете все остальное.

Я предполагаю, что код, который вы хотите использовать для модульного тестирования, является потребителем вашего компонента доступа к данным, так как это наиболее распространенный сценарий. Вы можете заблокировать доступ к данным, только если вы программируете через интерфейс . Это означает, что вы должны скрыть детали реализации L2S за интерфейсом, чтобы потребляющий код не знал, какую реализацию он использует в настоящее время.

Следствием этого является то, что ленивая загрузка - это деталь реализации, о которой вам не нужно беспокоиться при модульном тестировании, поскольку в модульном тесте вообще не следует использовать L2S.

При заглушении уровня доступа к данным, вызов customers.Ordersобычно будет вызовом свойства заглушки в памяти.

2
13.10.2009 11:32:22
Другими словами, не использовать автоматически сгенерированные свойства отложенной загрузки? Вместо вызова customer.Orders (где customer имеет тип Customer, созданный Linq 2 Sql), вы должны создать OrderRepository, который реализует IOrderRepository, и заглушить это? Это то, что я делал, но, кажется, напрасно игнорировать использование функций отложенной загрузки Linq 2 Sql ...
Kevin Pang 13.10.2009 22:54:53
Да, это именно то, что я имею в виду, но то, что вы программируете на интерфейсе, который не учитывает детали реализации, не означает, что вы не можете использовать эти функции. Если вы находите полезными функции L2S с отложенной загрузкой, то обязательно используйте их, но вы должны делать это таким образом, чтобы потребитель не знал об этих деталях. Современные технологии ORM от Microsoft (L2S и EF) не очень хорошо подходят для этого способа работы с доступом к данным, но FWIW в следующей версии EF должен получить истинное постоянное невежество ...
Mark Seemann 13.10.2009 23:36:56
Имеет смысл. Я подумал, что это может быть так, но надеялся, что это не так и что я что-то упустил. Полагаю, я пока просто проигнорирую функции отложенной загрузки для модульного тестирования.
Kevin Pang 14.10.2009 00:31:32