Как смоделировать DbSet <T>.Load (), используя Moq? - PullRequest
0 голосов
/ 29 ноября 2018

Я пытаюсь выполнить модульное тестирование следующих строк кода:

myDbContext.myDbSet.Load()
myObservableCollection = myDbContext.myDbSet.Local

Мой метод тестирования выглядит следующим образом:

Dim dataMyDbSet = New List(Of myDbSet) From {
        new myDbSet() With{.Id=1},
        new myDbSet() With{.Id=1},
        new myDbSet() With{.Id=1}
        }.AsQueryable()

Dim myDbSetMock = New Mock(Of DbSet(of myDbSet))
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.Provider).Returns(dataMyDbSet.Provider)
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.Expression).Returns(dataMyDbSet.Expression)
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.ElementType).Returns(dataMyDbSet.ElementType)
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.GetEnumerator).Returns(dataMyDbSet.GetEnumerator)

myDbSetMock.Setup(Function(x) x.Local).Returns(New ObservableCollection(Of myDbSet)(dataMyDbSet))

Dim MyDbContextMock = New Mock(of dbCrashtestNcap)
MyDbContextMock.Setup(function (f) f.myDbSet).Returns(myDbSetMock.Object)

Dim crashService = New CrashService(MyDbContextMock.Object)
Dim result = crashService.GetOcNcapKlassen()

Assert.That(result.Count,[Is].EqualTo(3))

это возвращает мне NullReferenceException в первой строке с myDbContext.myDbSet.Load ()

Все мои попытки либо насмехаться над Load (), либо вернуть значение для myDbContext.myDbSet (так что NullPointerException не существует) потерпели неудачу

A (грязный) обходной путь, который работает, это изменить Load () в ToList (), но я бы предпочел оставить Load () или, по крайней мере, понять, есть ли решение.Заранее спасибо за помощь.Решением может быть C # или vb.net, это не так важно для меня

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Как уже упоминалось в комментариях Ивана Стоева (еще раз спасибо!), Моя проблема заключалась в том, что Load() не работает с универсальной версией IQueryable, но не с универсальной версией.Поэтому, чтобы решить эту проблему, я заменил мои четыре выше строки на следующие, и это работает:

myDbSetMock.As(of IQueryable).Setup(Function(m) m.Provider).Returns(dataMyDbSet.Provider)
myDbSetMock.As(of IQueryable).Setup(Function(m) m.Expression).Returns(dataMyDbSet.Expression)
myDbSetMock.As(of IQueryable).Setup(Function(m) m.ElementType).Returns(dataMyDbSet.ElementType)
myDbSetMock.As(of IQueryable).Setup(Function(m) m.GetEnumerator).Returns(dataMyDbSet.GetEnumerator)

Однако, если вы хотите использовать ToList (), требуется универсальная версия.

0 голосов
/ 29 ноября 2018

Вы уже успешно настроили макет для Local, который является свойством типа DbSet<T>, который вы также высмеяли.Метод Load является статическим (я считаю, что это даже метод расширения, но это не имеет значения для этого случая).Фреймворки, такие как Moq, используют прокси-методы для связывания, чтобы устанавливать макеты для различных типов объектов.Хотя это хорошее решение, оно запрещает вам высмеивать что-либо, кроме virtual или abstract типов, поэтому вы не можете смоделировать статический метод Load из коробки, используя Moq.

Что вы могли бысделать, это создать новый метод внутри вашего устройства, отметить его virtual и вызвать там метод Load:

   public class Unit
    {
        public void YourMethod()
        {
            // .. do stuff
            CallStaticMethod(/* maybe pass parameters? */);
            // .. do more stuff
        }

        public virtual void CallStaticMethod()
        {
            // call static method
            Console.WriteLine("This is a static method call!");
        }
    }

    public class UnitUnderTest : Unit
    {
        public override void CallStaticMethod()
        {
            // do whatever you want during testing only

            // possibly call base.CallStaticMethod() to execute base method.
        }
    }

Теперь в вашем модульном тесте вам нужно использовать UnitUnderTest и изменить егокласс, чтобы он соответствовал вашим потребностям.

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