Я относительно новичок в Moq, и у меня сложный случай, чтобы высмеивать его, и я немного застрял. Я надеялся, что опытный пользователь Moq может дать мне совет по этому поводу:
Внутри моей ViewModel ctor вызывает этот метод загрузки:
public void LoadCategories()
{
Categories = null;
BookDataService.GetCategories(GetCategoriesCallback);
}
Я бы хотел издеваться над Сервисом. Но так как метод сервиса недействителен, а возврат всегда осуществляется через обратный вызов, он становится слишком сложным для меня.
private void GetCategoriesCallback(ObservableCollection<Category> categories)
{
if (categories != null)
{
this.Categories = categories;
if (Categories.Count > 0)
{
SelectedCategory = Categories[0];
}
LoadBooksByCategory();
}
}
Поскольку это было не так уж плохо, как вы можете видеть, есть другой LoadMethod внутри, называемый LoadBooksByCategory ()
public void LoadBooksByCategory()
{
Books = null;
if (SelectedCategory != null)
BookDataService.GetBooksByCategory(GetBooksCallback, SelectedCategory.CategoryID, _pageSize);
}
private void GetBooksCallback(ObservableCollection<Book> books)
{
if (books != null)
{
if (Books == null)
{
Books = books;
}
else
{
foreach (var book in books)
{
Books.Add(book);
}
}
if (Books.Count > 0)
{
SelectedBook = Books[0];
}
}
}
Так что теперь моя настройка Mock:
bool submitted = false;
Category selectedCategory = new Category{CategoryID = 1};
ObservableCollection<Book> books;
var mockDomainClient = new Mock<TestDomainClient>();
var context = new BookClubContext(mockDomainClient.Object);
var book = new Book
{
...
};
var entityChangeSet = context.EntityContainer.GetChanges();
var mockService = new Mock<BookDataService>(context);
mockService.Setup(s => s.GetCategories(It.IsAny<Action<ObservableCollection<Category>>>()))
.Callback<Action<ObservableCollection<Category>>>(action => action(new ObservableCollection<Category>{new Category{CategoryID = 1}}));
mockService.Setup(s => s.GetBooksByCategory(It.IsAny<Action<ObservableCollection<Book>>>(), selectedCategory.CategoryID, 10))
.Callback<Action<ObservableCollection<Book>>>(x => x(new ObservableCollection<Book>()));
//Act
var vm = new BookViewModel(mockService.Object);
vm.AddNewBook(book);
vm.OnSaveBooks();
//Assert
EnqueueConditional(() => vm.Books.Count > 0);
EnqueueCallback(() => Assert.IsTrue(submitted));
Как видите, я создал две настройки для каждого служебного вызова, однако из-за их обратного вызова и последовательной зависимости это очень запутанно.
например, второй вызов службы GetBooksByCategory () никогда не будет вызван, если свойство Selectedcategory в viewmodel останется нулевым. Но единственное, что я могу здесь высмеять, это на самом деле только сервис, внедренный в модель представления. Итак, как я собираюсь повлиять на это внутри viewmodel через мой обратный вызов? :) Имеет ли это смысл?
В самом конце я ожидаю, что экземпляры ObservableCollection Books будут инстанцированы и, возможно, заполнены некоторыми тестовыми данными (чего я здесь не делаю, я рад, если они хотя бы инстанцированы, так что я могу протестировать добавление новой книги в пустую коллекцию)
Это идея. Как только я могу понять это, я думаю, что я правильно понимаю Moq. :)