2009-07-27 79 views
2

我正在做一些控制器的單元測試,我正在嘲笑業務組件。 BC有一個公共事件,當控制器構建時,我讓控制器收聽。如何聆聽嘲笑對象的事件?

我遇到的問題是我不斷收到一個期望錯誤消息: 「IBC.add_MessageRaised(MessageEventHandler)Expected#:1 Actual#:0」。

但是,在我的測試中我沒有這種期望。我想知道是否需要將控制器設置爲偵聽模擬對象(本例中爲BC)上的事件。有沒有另外一種方法讓控制器能夠聽到來自模擬的事件?

我也試圖想辦法讓模擬器引發MessageRaised事件,但這可能完全是另一個問題。

下面是代碼:

業務組件接口

public interface IBC 
{ 
    event MessageEventHandler MessageRaised; 
    XmlDocument GetContentXml(string path); 
} 

控制器

private readonly IBC _bc; 

public Controller(IBC bc) 
{ 
    _bc = bc; 
    _bc.MessageRaised += MessageWatch; 
} 
private void MessageWatch(object sender, MessageEventArgs e) 
{ 
    if (MessageRaised != null) 
     MessageRaised(sender, e); 
} 

單元測試

MockRepository Mockery = new MockRepository(); 
TFactory _tFac; 
IView _view; 
Presenter _presenter = new Presenter(); 
IBC _bc = Mockery.DynamicMock<IBC>(); 
Controller _controller = new Controller(_bc); 
_tFac = new TFactory(Mockery); 
_tFac.Create(ref _view, ref _presenter, ref _controller); 

[Test] 
public void View_OnGetContentXmlButtonClick_Should_SetXmlInView() 
{ 
    //SETUP 
    XmlDocument xmlDocument = new XmlDocument(); 
    using (Mockery.Record()) 
    { 
     SetupResult.For(_view.FilePath).Return("C:\Test.txt"); 
     Expect.Call(_bc.GetContentXml("C:\Test.txt")).Return(xmlDocument); 
     _view.Xml = xmlDocument.InnerXml; 
    } 

    //EXECUTE 
    using (Mockery.Playback()) 
    { 
     _presenter.View_OnGetContentXmlButtonClick(); 
    } 
} 

回答

0

我把它組合了幾件事情的工作(不完全知道它是如何工作的,但它確實):

IEventRaiser _raiser; 
MockRepository Mockery = new MockRepository(); 
TFactory _tFac; 
IView _view; 
Presenter _presenter = new Presenter(); 
IBC _bc = Mockery.DynamicMock<IBC>(); 
_bc.MessageRaised += null; 
_raiser = LastCall.GetEventRaiser(); 
Controller _controller = new Controller(_bc); 
Mockery.BackToRecord(_bc,BackToRecordOptions.None); 
_tFac = new TFactory(Mockery); 
_tFac.Create(ref _view, ref _presenter, ref _controller); 

本作中的問題作測試,以及讓我養的來自其他測試中的Mock對象的事件,如:

[Test] 
public void View_OnGetContentXmlButtonClick_When_FileDoesNotExist_Should_RelayMessage() 
{ 
    //SETUP 
    XmlDocument xmlDocument = new XmlDocument(); 
    using (Mockery.Record()) 
    { 
     SetupResult.For(_view.FilePath).Return("C:\Test.txt"); 
     Expect.Call(_bc.GetContentXml("C:\Test.txt")).Return(null); 
     _view.Xml = xmlDocument.InnerXml; 
     _view.Message = MESSAGE_FILE_NOT_EXIST; 
    } 

    //EXECUTE 
    using (Mockery.Playback()) 
    { 
     _presenter.View_OnGetContentXmlButtonClick(); 
     _raiser.Raise(_bc, new MessageEventArgs(MESSAGE_FILE_NOT_EXIST)); 
    } 
} 

希望其他人認爲這有用!

3

看來下面的代碼使用一個模擬對象的d,通過使用它,則會記錄的期望:

Controller _controller = new Controller(_bc); 

您使用的是模擬對象是這樣的:

_bc.MessageRaised += MessageWatch; 

其結果是,你已經建立了一個期望,一個事件處理程序被添加到_bc.MessageRaised。這在播放模塊中不會發生,所以會引發錯誤。

另請參閱this question有關對象何時進入記錄狀態的信息。說實話,我也不明白爲什麼有一個明確的記錄語法,如果對象無論如何進入記錄狀態。

+0

謝謝!另一個問題幫助了一些,因爲我不知道BackToRecord()方法。 – 2009-07-28 16:22:42

0

這是我如何處理從模擬對象引發事件:

 port.DataPacketReceived += null; 
     packetReceivedRaiser = 
      LastCall.IgnoreArguments().Repeat.Any().GetEventRaiser(); 

在這種情況下,端口是一個名爲DataPacketReceived事件的模仿對象。

理想情況下,我總是試圖將我的模擬對象放入回放模式,然後再將它們傳遞到被測系統。這避免了任何「意想不到的期望」。