![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
InitRepository(kernel); //потом сделаем
return kernel; } Создадим MockRepository: (/Mock/Repository/MockRepository.cs): public partial class MockRepository: Mock< IRepository> { public MockRepository(MockBehavior mockBehavior = MockBehavior.Strict) : base(mockBehavior) { GenerateRoles(); GenerateLanguages(); GenerateUsers();
} } (/Mock/Repository/Entity/Language.cs) namespace LessonProject.UnitTest.Mock { public partial class MockRepository { public List< Language> Languages { get; set; }
public void GenerateLanguages() { Languages = new List< Language> (); Languages.Add(new Language() { ID = 1, Code = " en", Name = " English" }); Languages.Add(new Language() { ID = 2, Code = " ru", Name = " Русский" }); this.Setup(p => p.Languages).Returns(Languages.AsQueryable()); } } }
(/Mock/Repository/Entity/Role.cs) public partial class MockRepository { public List< Role> Roles { get; set; }
public void GenerateRoles() { Roles = new List< Role> (); Roles.Add(new Role() { ID = 1, Code = " admin", Name = " Administrator" });
this.Setup(p => p.Roles).Returns(Roles.AsQueryable()); } }
(/Mock/Repository/Entity/User.cs)
public partial class MockRepository { public List< User> Users { get; set; }
public void GenerateUsers() { Users = new List< User> ();
var admin = new User() { ID = 1, ActivatedDate = DateTime.Now, ActivatedLink = " ", Email = " admin", FirstName = " ", LastName = " ", Password = " password", LastVisitDate = DateTime.Now, };
var role = Roles.First(p => p.Code == " admin"); var userRole = new UserRole() { User = admin, UserID = admin.ID, Role = role, RoleID = role.ID };
admin.UserRoles = new EntitySet< UserRole> () { userRole }; Users.Add(admin);
Users.Add(new User() { ID = 2, ActivatedDate = DateTime.Now, ActivatedLink = " ", Email = " chernikov@gmail.com", FirstName = " Andrey", LastName = " Chernikov", Password = " password2", LastVisitDate = DateTime.Now });
this.Setup(p => p.Users).Returns(Users.AsQueryable()); this.Setup(p => p.GetUser(It.IsAny< string> ())).Returns((string email) => Users.FirstOrDefault(p => string.Compare(p.Email, email, 0) == 0)); this.Setup(p => p.Login(It.IsAny< string> (), It.IsAny< string> ())).Returns((string email, string password) => Users.FirstOrDefault(p => string.Compare(p.Email, email, 0) == 0)); } }
Рассмотрим, как работает Mock. У него есть такой хороший метод, как Setup (опять?! сплошной сетап!), который работает таким образом: this.Setup(что у нас запрашивают).Returns(что мы отвечаем на это);
Например: this.Setup(p => p.WillYou()).Returns(true); Рассмотрим подробнее, какие еще могут быть варианты: · Методы var mock = new Mock< IFoo> (); mock.Setup(foo => foo.DoSomething(" ping")).Returns(true);
o параметр out var outString = " ack"; mock.Setup(foo => foo.TryParse(" ping", out outString)).Returns(true);
o ссылочный параметр var instance = new Bar(); mock.Setup(foo => foo.Submit(ref instance)).Returns(true); o зависимость от входного параметра и возвращаемого значения (можно и несколько параметров) mock.Setup(x => x.DoSomething(It.IsAny< string> ())) .Returns((string s) => s.ToLower());
o кидаем исключение mock.Setup(foo => foo.DoSomething(" reset")).Throws< InvalidOperationException> (); mock.Setup(foo => foo.DoSomething(" ")).Throws(new ArgumentException(" command");
o возвращает различные значения для (???) и использование Callback var mock = new Mock< IFoo> (); var calls = 0; mock.Setup(foo => foo.GetCountThing()) .Returns(() => calls) .Callback(() => calls++);
· Соответсвие на аргументы o любое значение
mock.Setup(foo => foo.DoSomething(It.IsAny< string> ())).Returns(true);
o условие через Func< bool, T>
mock.Setup(foo => foo.Add(It.Is< int> (i => i % 2 == 0))).Returns(true);
o нахождение в диапазоне
mock.Setup(foo => foo.Add(It.IsInRange< int> (0, 10, Range.Inclusive))).Returns(true);
o Regex выражение mock.Setup(x => x.DoSomething(It.IsRegex(" [a-d]+", RegexOptions.IgnoreCase))).Returns(" foo"); · Свойства o Любое свойство mock.Setup(foo => foo.Name).Returns(" bar");
o Любой иерархии свойство mock.Setup(foo => foo.Bar.Baz.Name).Returns(" baz");
· Обратные вызовы (callback) o Без параметров mock.Setup(foo => foo.Execute(" ping")) .Returns(true) .Callback(() => calls++);
o С параметром mock.Setup(foo => foo.Execute(It.IsAny< string> ())) .Returns(true) .Callback((string s) => calls.Add(s));
o С параметром, немного другой синтаксис mock.Setup(foo => foo.Execute(It.IsAny< string> ())) .Returns(true) .Callback< string> (s => calls.Add(s));
o Несколько параметров mock.Setup(foo => foo.Execute(It.IsAny< int> (), It.IsAny< string> ())) .Returns(true) .Callback< int, string> ((i, s) => calls.Add(s));
o До и после вызова mock.Setup(foo => foo.Execute(" ping")) .Callback(() => Console.WriteLine(" Before returns")) .Returns(true) .Callback(() => Console.WriteLine(" After returns")); · Проверка (Mock объект сохраняет количество обращений к своим параметрам, тем самым мы также можем проверить правильно ли был исполнен код) o Обычная проверка, что был вызван метод Execute с параметром “ping” mock.Verify(foo => foo.Execute(" ping"));
o // С добавлением собственного сообщения об ошибке mock.Verify(foo => foo.Execute(" ping"), " When doing operation X, the service should be pinged always");
o Не должен был быть вызван ни разу mock.Verify(foo => foo.Execute(" ping"), Times.Never());
o Хотя бы раз должен был быть вызван mock.Verify(foo => foo.Execute(" ping"), Times.AtLeastOnce());
mock.VerifyGet(foo => foo.Name);
o Должен был быть вызван именно сеттер для свойства mock.VerifySet(foo => foo.Name);
o Должен был быть вызван сеттер со значением “foo” mock.VerifySet(foo => foo.Name = " foo");
o Сеттер должен был быть вызван со значением в заданном диапазоне mock.VerifySet(foo => foo.Value = It.IsInRange(1, 5, Range.Inclusive)); Хорошо, этого нам пока хватит, остальное можно будет почитать здесь: https://code.google.com/p/moq/wiki/QuickStart Возвращаемся обратно в UnitTestSetupFixture.cs (/Setup/UnitTestSetupFixture.cs) и инициализируем конфиг: protected virtual void InitRepository(StandardKernel kernel) { kernel.Bind< MockRepository> ().To< MockRepository> ().InThreadScope(); kernel.Bind< IRepository> ().ToMethod(p => kernel.Get< MockRepository> ().Object); } Проверим какой-то наш вывод, например класс /Default/Controllers/UserController: cs: [Test] public void Index_GetPageableDataOfUsers_CountOfUsersIsTwo() { //init var controller = DependencyResolver.Current.GetService< Areas.Default.Controllers.UserController> (); //act var result = controller.Index();
Assert.IsInstanceOf< ViewResult> (result); Assert.IsInstanceOf< PageableData< User> > (((ViewResult)result).Model); var count = ((PageableData< User>)((ViewResult)result).Model).List.Count();
Assert.AreEqual(2, count); } В BaseController.cs (/LessonProject/Controllers/BaseController.cs) уберем атрибуты Inject у свойств Auth и Config (иначе выделенная строка не сможет проинициализовать контроллер и вернет null). Кстати о выделенной строке. Мы делаем именно такую инициализацию, чтобы все Inject-атрибутованные свойства были проинициализированы. Запускаем, и, правда, count == 2. Отлично, MockRepository работает. Вернем назад атрибуты Inject. Кстати, тесты не запускаются обычно в дебаг-режиме, чтобы запустить Debug надо сделать так: Теперь поработаем с Config. Это будет круто!
|