【发布时间】:2011-02-14 10:51:16
【问题描述】:
我对 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];
}
}
}
现在我的模拟设置:
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));
如您所见,我为每个服务调用创建了两个设置,但是由于它们的回调和顺序依赖性,它非常混乱。
例如,如果视图模型中的 Selectedcategory 属性保持为空,则永远不会调用第二个服务调用 GetBooksByCategory()。但我在这里唯一可以模拟的实际上只是注入到视图模型中的服务。那么我将如何通过回调影响视图模型内部的内容呢? :) 有意义吗?
最后,我希望 ObservableCollection Books 被实例化并且可能填充了一些测试数据(我在这里没有这样做,如果它至少被实例化,我很高兴,这样我就可以测试添加一本新书到一个空集合)
就是这样。一旦我能理解这一点,我想我就正确理解了 Moq。 :)
【问题讨论】:
标签: .net unit-testing moq