powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / MVC - Загадочный Moq
8 сообщений из 8, страница 1 из 1
MVC - Загадочный Moq
    #38967067
ValGer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пытаясь разобраться с имитацией объектов наткнулся на статью "SteveMichael How do I use Moq with ASP.NET MVC?", в которой имитируется работа с базой данных без самой базы. То есть, имеется интерфейс, который, видимо и должен смотреть на класс "физического" взаимодействия с сервером
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
namespace SteveMichael
{
    public interface IPersonRepository
    {
        Person GetPersonById(int personId);
        //.....................................................
    }
}



Однако, реализация этого интерфейса отсутствует!
С другой стороны этот интерфейс внедрён в сервис работы с данными
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
namespace SteveMichael
{
    public class PersonService
    {
        [color=red]private readonly IPersonRepository _personRepository;[/color]
        public PersonService(IPersonRepository personRepository)
        {
            if (personRepository == null) { throw new ArgumentNullException("personRepository"); }

            _personRepository = personRepository;
        }

        public Person GetByPersonId(int personId)
        {
            return _personRepository.GetPersonById(personId);
        }
    }
}



И теперь самое интересное - реализация теста с моими заметками как я это понимаю (возможно, неправильно!)
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
namespace PersonUnitTest
{
    // http://stevemichael.net/how-do-i-use-moq-with-asp-net-mvc/
    [TestClass]
    public class PersonServiceTests
    {
        [TestMethod]
        public void GetByPersonId_ValidId_Person()
        {
            // Arrange
            const int personId = 1;
            Person person = new Person()
            {
                PersonId = personId,
                FirstName = "Jim",
                LastName = "Smith"
            };

            Mock<IPersonRepository> mockPersonRepository = new Mock<IPersonRepository>();
            mockPersonRepository.Setup(r => r.GetPersonById(1)).Returns(person);
            /* 
             * Как я понимаю, смысл этой записи заключается в том, что когда мы обращаемся 
             * к репозиторию (точнее к интерфейсу) к его методу получения  
             * Person по его идентификатору personId = 1, то получаем экземпляр «person».
             * Своеобразный условный оператор?
            */

            var personService = new PersonService(mockPersonRepository.Object);

            // Act
            Person result = personService.GetByPersonId(personId);  // А что и откуда тут берётся?

            // Assert
            Assert.AreEqual(person, result);
        }
    }
}



Вот тут самое загадочное это Act - откуда берётся result, если интерфейс не реализован? То есть, .GetByPersonId(personId) вычислить невозможно - нет кода!!! Причём, если personId=1, то тест проходит, а если возьму например, в операторе Setup(r => ...) и поставлю 2, то тест не проходит - даёт null.
Какова "механика" этого процесса?
...
Рейтинг: 0 / 0
MVC - Загадочный Moq
    #38967135
ValGer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ValGer,

То есть, поразмышляв, пришёл к выводу, что вся эта "тряхомудь" проверяет не то, что 4 = 2 * 2 (4 - person; 2 * 2 - result), а то, что 4 = 4
Или я не прав?
...
Рейтинг: 0 / 0
MVC - Загадочный Moq
    #38967142
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ValGerправ
...
Рейтинг: 0 / 0
MVC - Загадочный Moq
    #38967222
Pallaris
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ValGerКакова "механика" этого процесса?

Механика такова, что обычно нужно тестировать класс, который использует в работе некий интерфейс. Например, метод контроллера, который отберет первые пять записей из репозитория. Вот мы и мокаем репозиторий и проверяем, как работает метод. А у тебя в примере ты мокаешь интерфейс и проверяешь, как работает мок :)
...
Рейтинг: 0 / 0
MVC - Загадочный Moq
    #38968232
ProBiotek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ValGer,

Вам нужно разобраться что такое юнит-тестинг, и мок объекты в принципе. Прежде чем рассматривать на примере применения MVC или чего-то еще.

По сути мок объекты нужны лишь для тестирования алгоритма .

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

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

Поэтому и существуют мок-фреймворки. Которые через рефлексию на лету создают мок объект над любым интерфейсом. Созданный мок объект тут же конфигурируется, чтобы задать его поведение.
Это нужно для того, чтобы мы тестировали именно алгоритм, а не "наведенные проблемы" от реальных объектов.
Например. Сложно написать тест, полагаясь на DateTime.Now. Но создав мок, и сконфигурировав, чтобы он возвращал конкретную дату, мы можем четко тестировать алгоритм.

В приведенном Вами коде это происходит тут:
Код: c#
1.
2.
Mock<IPersonRepository> mockPersonRepository = new Mock<IPersonRepository>();
mockPersonRepository.Setup(r => r.GetPersonById(1)).Returns(person);



На лету создается мок, и указывается что при обращении к методу GetPersonById с передачей ему параметра 1, он должен вернуть созданный объект person.
Реализации нету. Точнее она создается на лету - каждый раз, когда мы конструируем мок объект.


PS. Есть моки, а есть стабы :) Почитай статейку Фаулера о разнице между ними. Чтобы уж совсем прослыть гуру IoC.
IoC это тоже тесно связанная тема, которую нужно понимать, раз уж начали изучать.
...
Рейтинг: 0 / 0
MVC - Загадочный Moq
    #38968245
ProBiotek
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ValGer,

вот отличная книга которая очень хорошо все объясняет
http://www.ozon.ru/context/detail/id/22104901/

начиная с самых азов, и заканчивая кучей реальных примеров под различные IoC Container.
...
Рейтинг: 0 / 0
MVC - Загадочный Moq
    #38969419
ValGer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ProBiotek,

Это я, в общем-то, понимаю и ваши слова подтверждают, что в этом конкретном случае проверяется, что 4 = 4 (см. выше) , то есть, фактически проходит ли обращение к интерфейсу и ничего более.
Книжка действительно хорошая, но уж больно дорогая, до и хотелось бы её в электронном варианте.
Спасибо!
...
Рейтинг: 0 / 0
MVC - Загадочный Moq
    #38971946
ValGer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ProBiotek,

Книжку скачать не удалось - везде просят номер телефона, а это может быть фатально. Но зато нашел сайт, где её можно читать с экрана:
http://smarly.net/dependency-injection-in-net
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / MVC - Загадочный Moq
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]