【发布时间】:2011-07-02 04:56:07
【问题描述】:
我在 ASP.NET WebForms 应用程序中使用 Model-View-Presenter 的样板实现。 My View 有两个后果事件,一个表明用户在域模型上填写了足够的字段以启动重复检查,另一个是常规的 Save 事件。我的伪代码如下所示:
public class ItemNewPresenter : PresenterBase<IItemNewView>
{
public IItemService Service { get; private set; }
public IItemNewView View { get; private set; }
public ItemNewPresenter(IItemService service, IItemNewView view)
{
Service = service;
View = view;
View.OnSave += DoItemSave;
View.OnItemIsDuplicateCheck+= DoItemIsDuplicateCheck;
}
private void DoItemIsDuplicateCheck(object sender, CheckItemDuplicateEventArgs e)
{
CheckForItemDuplication(e.Item);
}
private void CheckForItemDuplication(Item item){
if (Service.IsDuplicateItem(item))
{
View.RedirectWithNotification(BuildItemUrl(item), "This item already exists");
}
}
private void DoItemSave(object sender, SaveItemEventArgs e)
{
DoItemIsDuplicateCheck(this, e.ToItemDuplicateEventArgs());
Service.Save(e.Item);
}
}
这是我的测试,用于确保在从视图中引发 OnItemIsDuplicateCheck 时我的演示者行为正常:
[Test]
public void presenter_checking_for_existing_item_should_call_redirect_if_found()
{
var service = new Mock<IItemService>();
var view = new Mock<IItemNewView>();
var presenter = new ItemNewPresenter (service.Object, view.Object);
var onCheckExistingHandler = view.CreateEventHandler <CheckItemDuplicateEventArgs>();
view.Object.OnExistingDenominatorCheck += onCheckExistingHandler;
var eventArgs = new CheckItemDuplicateEventArgs();
service.Setup(s => s.IsDuplicate(It.Is<CheckItemDuplicateEventArgs>(c => c.Equals(eventArgs)))).Returns(true);
onCheckExistingHandler.Raise(eventArgs);
view.Verify(v => v.RedirectWithNotification(It.IsAny<String>(), It.IsAny<string>()), Times.Once());
service.Verify();
}
为了保持一致性,我希望在 View 引发 OnSave 事件时触发相同的重复检查。我的问题是,当我要验证的方法之一 (CheckForItemDuplication) 在被测类上声明时,我应该如何编写测试。验证 SUT 上的方法调用(错误)的替代方法是使用 lots 的重复代码编写我的保存测试(我的所有模拟的设置和断言将从上述测试中复制)并且它也使单元测试不那么集中。
[Test]
public void presenter_saving_item_should_check_for_dupe_and_save_if_not_one() {
//duplicate mocks/setups/asserts from duplicate check fixture
//additional mocks/setups/asserts to test save logic
}
我认为 TDD 建议将此私有方法拉出到一个单独的类中,该类与我的 Presenter 协作并通过 DI 注入。但是为我的 Presenter 添加另一个依赖项以获取似乎不值得成为独立抽象的功能 *并且*表示我的 Presenter 的内部实现细节似乎......嗯......疯狂。我在这里离基地很远吗?必须有一些设计模式或重构我可以应用,以避免将私有方法转换为依赖项。
【问题讨论】:
标签: c# unit-testing oop dependency-injection tdd