Могу ли я высмеивать Objectresult <T>Entity Framework, используя MOQ - PullRequest
5 голосов
/ 25 мая 2010

Я использую Entity Frameowrk 4.0, и я вызываю хранимую процедуру, которая возвращает ObjectResult, и я попытался использовать MOQ и не смог смоделировать ObjectResult. Кто-нибудь смог издеваться над ObjectResult, используя moq? ​​

ТИА Yaz

Ответы [ 4 ]

4 голосов
/ 14 ноября 2012

У меня тоже есть эта проблема; Я использую дизайн базы данных и шаблон EF 4.x DbContext Generator для создания моего DbContext.

Я изменяю генератор контекста следующими способами:

  1. Вместо DbSet для наборов сущностей я возвращаю IDbSet ; это позволяет мне использовать InMemoryDbSet для модульного тестирования (Google для реализаций);
  2. Вместо ObjectResult для хранимых процедур я возвращаю IEnumerable . Внутри виртуального метода, созданного для хранимой процедуры, я загружаю ObjectResult в список и возвращаю это;
  3. Наконец, я извлекаю интерфейс, отображающий наборы сущностей и импорт функций. Это означает, что я могу затем смоделировать весь DbContext для супер-скоростных модульных тестов. Разумеется, вы все равно должны писать интеграционные тесты, которые проверяют работоспособность базы данных.
2 голосов
/ 08 мая 2015

ObjectResult обычно используется с Linq, поэтому он в основном используется как IEnumerable. Даже если объект запечатан, вы можете смоделировать его и настроить поведение IEnumerable.

Вот пример кода, где TResult - это тип результата хранимой процедуры, а TDbContext - это DbContext, и он возвращает 1 элемент.

var valueEnumerator = new TResult[] { new TResult() }.GetEnumerator();

var mockStoredProcedure = new Mock<ObjectResult<TResult>();
mockStoredProcedure.Setup(x => x.GetEnumerator()).Returns(valueEnumerator);

var mockEntities = new Mock<TDbContext>();
mockEntities.Setup(x => x.[stored procedure method]()).Returns(mockStoredProcedure.Object);

Вы можете добавить любые значения в массив в примере выше или использовать любую другую коллекцию (вам нужен только перечислитель).

Дайте этот код попробовать. У меня работает с EF 6.1.2 и Moq 4.2

2 голосов
/ 06 июня 2010

ObjectResult ( в соответствии с документами MSDN ) является запечатанным классом, так что его нельзя издеваться. Работа с библиотеками Mocking, такими как Moq, заключается в том, что когда вы делаете что-то вроде

Mock<Foo> fooMock = new Mock<Foo>();

Он генерирует (используя Reflection.Emit и другие магические трюки) класс, который выглядит примерно так

public class FooMockingProxy : Foo {

    public override void This() {
        // Mocking interceptors to support Verify and Setup
    }

    public override string That() {
        // Mocking interceptors to support Verify and Setup
    }

}

т.е. Он берет класс (интерфейс), который вы хотите Mock и подклассы его (или реализует его в случае интерфейса). Это позволяет ему использовать инструментарий, который позволяет ему проверять, был ли вызван метод, или возвращает определенное значение (это поддерживает различные методы Setup и Verify). Ограничения к этому методу насмешек: -

  • Запечатанные классы (не могут быть разделены на подклассы)
  • Частные участники (не могут быть доступны из подкласса)
  • Методы или классы свойств, которые не являются виртуальными (и поэтому не могут быть переопределены).

Одна из техник, которую вы можете использовать при приближении к закрытым классам, - это обернуть их в какой-нибудь интерфейс, который можно использовать для моделирования. В качестве альтернативы вы можете попробовать Mock интерфейса, который реализует запечатанный класс, который потребляет только ваш код.

0 голосов
/ 06 сентября 2016

Я не мог найти способ смоделировать запечатанный класс, и хотел проверить, что параметры хранимой процедуры соответствуют объектной модели. Вот мое решение:

 namespace CardiacMonitoringTest
{
    [TestClass]
    public class CardiacMonitoringDataTest
    {
        [TestMethod]
        public void TestEntityStoredProcedure()
        {
            List<string> SPExceptions = new List<string>();
            SPExceptions.Add("AfibBurdenByDay");
            SPExceptions.Add("GetEventTotalsByCategory");

            EntitiesCon db = new EntitiesCon();
            foreach (MethodInfo mi in typeof(EntitiesCon).GetMethods())
            {

                string ptype = mi.ReturnType.Name;
                if (ptype.IndexOf("ObjectResult") > -1)
                {
                    List<SqlParameter> ExtractedParameters = SPListParm(ConfigurationManager.ConnectionStrings["CardiacMonitoring"].ConnectionString, mi.Name);
                ExtractedParameters = ExtractedParameters.Where(a => a.ParameterName != "@RETURN_VALUE" && a.ParameterName != "@TABLE_RETURN_VALUE").ToList();
                ParameterInfo[] EntityParameters = mi.GetParameters();
                if ((from b in SPExceptions where b.ToLower() == mi.Name.ToLower() select b).Count() > 0)
                {
                    continue;
                }
                foreach (ParameterInfo pi in EntityParameters)
                {


                        try
                        {
                            Assert.IsTrue(
                                (from a in ExtractedParameters where pi.Name.ToLower() == a.ParameterName.Replace("@", "").ToLower() select a).Count() == 1);
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteLine("Failed SP:" + mi.Name + " at parameter:" + pi.Name);
                            throw (ex);
                        }
                    try
                    {
                        Assert.IsTrue(EntityParameters.Count() == ExtractedParameters.Count());
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine("Failed SP:" + mi.Name + " on parameter count:" + EntityParameters.Count() + " with detected count as:" + ExtractedParameters.Count());
                        throw (ex);
                    }
                }
            }
            }
        }

        private List<SqlParameter> SPListParm(string ConnectionString, string SPName)
        {
            try
            {
                SqlConnection conn = new SqlConnection(ConnectionString);
                SqlCommand cmd = new SqlCommand(SPName, conn);
                cmd.CommandType = CommandType.StoredProcedure;
                conn.Open();
                SqlCommandBuilder.DeriveParameters(cmd);
                SqlParameter[] prmDetectParameters = new SqlParameter[cmd.Parameters.Count];
                cmd.Parameters.CopyTo(prmDetectParameters, 0);
                List<SqlParameter> toReturn = new List<SqlParameter>();
                toReturn.AddRange(prmDetectParameters);
                return (toReturn);
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Failed detecting parameters for SP:" + SPName);
                throw (ex);
            }
        }
    }
}
...