我在ASP.NET WebForms應用程序中使用Model-View-Presenter的樣板實現。我的視圖有兩個結果事件,一個表示用戶在域模型上填充了足夠的字段以啓動重複檢查,另一個是常規的保存事件。我的僞代碼如下所示:TDD可以強制創建「假」依賴關係
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方法調用(壞)的替代方法是用重複代碼編寫我的保存測試批次(我的所有嘲笑的設置和斷言都將從上述測試中複製),並且還會使單元測試不那麼專注。
[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建議拉這個私有方法到一個單獨的類,它與我的演講合作,並會通過DI注入。但是,向我的Presenter添加另一個依賴關係,看起來不值得作爲獨立抽象的功能*和*表示我的Presenter的內部實現細節,看起來......好吧......太瘋狂了。我在這裏基地?必須有一些設計模式或重構我可以應用,這將避免需要將私有方法變成依賴項。
有趣的方法,但我覺得必須有更好的方法。正如你所指出的,我試圖測試的代碼是SUT的私有實現細節,並且永遠不需要通過消費類注入。引入一個新的類來封裝內部行爲只是爲了實現免費的測試代碼似乎徹頭徹尾的瘋狂:( – 2011-02-26 17:22:55