Как издеваться над ObjectContext или ObjectQuery <T> в Entity Framework?

Как издеваться над ObjectContext или ObjectQuery в Entity Framework?

Трудно дать вам хороший ответ на ваш вопрос, если вы не сообщите нам, какую проблему вы пытаетесь решить. Что именно вы пытаетесь проверить?

Craig Stuntz 06.01.2009 17:07

Похоже, здесь ответили: stackoverflow.com/questions/2065796/…

Phil Peace 30.06.2011 13:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
22
2
9 681
3

Ответы 3

Базовые фреймворки макетов могут создавать макеты только для интерфейсов и абстрактных классов (но только для абстрактных / виртуальных методов).

Поскольку ObjectContext не является ни абстрактным, ни интерфейсом, издеваться над ним не так-то просто. Однако, поскольку контейнер конкретной модели создается как частичный класс (если вы используете конструктор), вы можете извлекать из него необходимые методы / свойства в интерфейс. В своем коде вы можете использовать только интерфейс, который впоследствии можно будет имитировать.

С ObjectQuery это немного проще, поскольку он имеет базовый интерфейс (например, IQueryable), который в основном содержит все необходимые операции, которые вам обычно нужны (и требуются для LINQ). Таким образом, вы должны предоставить IQueryable вместо ObjectQuery в своей бизнес-логике, и вы можете создать макет для этого интерфейса.

Другой альтернативой является скрытие всей логики, связанной с доступом к данным, на отдельном уровне (с минимальной логикой), тестирование этого уровня с помощью интеграционных тестов и имитация его, чтобы иметь возможность модульного тестирования других уровней.

Существуют инструменты (я знаю только Тип: Мок), которые используют хуки профилирования .NET для создания макетов. Эти инструменты не ограничиваются имитацией интерфейсов или абстрактных классов, но с их помощью вы можете имитировать практически все, включая невиртуальные и статические методы. С таким инструментом вам не нужно менять бизнес-логику, чтобы разрешить насмешку.

Хотя этот подход иногда бывает полезен, вы должны знать, что извлечение зависимостей для интерфейсов (IoC) не только полезно для имитации, но также уменьшает зависимости между вашими компонентами, что также имеет другие преимущества.

Лично мне больше всего нравится Носорог.Моксы из бесплатных инструментов, но мы также используем Тип: Мок, который также является отличным продуктом (но за него нужно платить).

Потрясающе, я так долго пытался имитировать ObjectQuery, но никогда не думал заменить ObjectQuery на IQueryable в моем репозитории, я буквально хлопнул себя по лбу, когда прочитал это ...

CodeKiwi 23.01.2010 05:22

Да ... просто убедитесь, что вы не опускаетесь на уровень IEnumerable в абстракции, потому что тогда LINQ начинает вести себя по-другому (запросы будут выполняться в памяти, а не сервером db).

Gaspar Nagy 26.01.2010 17:07

Почему мы не можем просто создать фактический объект контекста, который будет использоваться в наших тестах? Поскольку мы не хотим, чтобы наши тесты влияли на производственную базу данных, мы всегда можем указать строку подключения, указывающую на тестовую базу данных. Перед запуском каждого теста создайте новый контекст, добавьте данные, которые вам понадобятся в вашем тесте, продолжите модульный тест, а затем в разделе очистки теста удалите все записи, которые были созданы во время теста. Единственным побочным эффектом здесь будет то, что идентификаторы автоинкремента будут использованы в тестовой базе данных, но поскольку это тестовая база данных - кого это волнует?

Я знаю, что в большинстве ответов на этот вопрос предлагается использовать проекты DI / IoC для создания интерфейсов для контекстов данных и т. д., Но причина, по которой я использую Entity Framework, заключается именно в том, чтобы не писать никаких интерфейсов для моих подключений к базе данных, объектных моделей и простых транзакций CRUD. Написание фиктивных интерфейсов для моих объектов данных и создание сложных запрашиваемых объектов для поддержки LINQ лишает смысла полагаться на хорошо протестированный и надежный Entity Framework.

Этот шаблон для модульного тестирования не нов - Рубин на рельсах использует его уже давно, и он отлично зарекомендовал себя. Так же, как .NET предоставляет EF, RoR предоставляет объекты ActiveRecord, и каждый модульный тест создает необходимые объекты, продолжает тесты, а затем удаляет все созданные записи.

Как указать строку подключения для тестовой среды? Поскольку все тесты находятся в отдельном тестовом проекте, достаточно добавить новый файл App.Config со строкой подключения для тестовой базы данных.

Только подумайте, сколько головной боли и боли это вас спасет.

В некоторых случаях я уверен, что предложенный вами метод полностью подходит. Что касается того, почему вы можете захотеть поиздеваться: 1 - Выполнение тестов с данными в памяти, вероятно, будет намного быстрее. 2 - Подключение к внешнему ресурсу вносит зависимость в ваш тест, делая его менее надежным. Как я уже сказал, все это не может быть проблемой для вас.

Christopher Thomas 22.11.2015 14:10

Я согласен с другими, вы не можете использовать Mock ObjectContext. Вам следует использовать EF DbContext, потому что вы можете имитировать базовый DbSet. Существует довольно много сообщений о том, как это сделать. Так что как это сделать, писать не буду. Однако, если вы абсолютно необходимо используете ObjectContext (по какой-то причине) и хотите провести модульное тестирование, вы можете использовать базу данных InMemory.

Сначала установите этот пакет Nuget: Effort (Entity Framework Fake ObjectContext Realization Tool), который использует NMemory в качестве базы данных. Установите пакет Effort.EF6:

PM> Install-Package Effort.EF6

using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using Effort;

public class DbContextHelper
{
    //Fake object you can drop this if you are using your own EF context
    private class DbObject
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

    //Fake EF context you can switch with you own EF context
    private class FakeDbContext : DbContext
    {
        public FakeDbContext(DbConnection connection)
            : base(connection, true) { }

        public virtual DbSet<DbObject> DbObjects { get; set; }
    }

    private FakeDbContext _dbContext;

    public DbContextHelper()
    {
        //In memory DB connection
        DbConnection effortConnection = DbConnectionFactory.CreatePersistent("TestInstanceName");
        _dbContext = new FakeDbContext(effortConnection);
    }

    //You can expose your context instead of the DbContext base type
    public DbContext DbContext => _dbContext;

    public ObjectContext ObjectContext => ((IObjectContextAdapter)_dbContext).ObjectContext;

    //Method to add Fake object to the fake EF context
    public void AddEntityWithState(string value, EntityState entityState)
    {
        DbContext.Entry(new DbObject() { Id = Guid.NewGuid(), Name = value }).State = entityState;
    }
}

Применение:

DbContextHelper _dbContextHelper = new DbContextHelper();
_dbContextHelper.AddEntityWithState("added", System.Data.Entity.EntityState.Added);
_dbContextHelper.AddEntityWithState("added", System.Data.Entity.EntityState.Modified);

var objs = _dbContextHelper.ObjectContext.GetObjectStateEntries(EntityState.Modified | EntityState.Added);

Вот и ваш объект в БД памяти.

Другие вопросы по теме