unit testing具有事件和委托的类

我是新手测试请帮助。

我有以下课程

public delegate void OnInvalidEntryMethod(ITnEntry entry, string message); public class EntryValidator { public event OnInvalidEntryMethod OnInvalidEntry; public bool IsValidEntry(ITnEntry entry, string ticker) { if (!IsFieldValid(entry, ticker.Trim().Length.ToString(), "0")) return false; return true; } private bool IsFieldValid(ITnEntry entry, string actual, string invalidValue) { if (actual == invalidValue) { RaiseInvalidEntryEvent(entry); return false; } return true; } private void RaiseInvalidEntryEvent(ITnEntry entry) { if (OnInvalidEntry != null) OnInvalidEntry(entry, "Invalid entry in list: " + entry.List.Name + "."); } } 

到目前为止,我已经编写了测试用例,但是我正在努力解决这个事件和委托,如下所示

 [TestFixture] public class EntryValidatorTests { private EntryValidator _entryValidator; private FakeTnEntry _selectedEntry; private string _ticker; [SetUp] public void Setup() { _entryValidator = new EntryValidator(); _ticker = "BOL"; } private FakeTnEntry MakeEntry(string ticker) { return new FakeTnEntry { Ticker = ticker}; } [Test] public void IsValidEntry_WithValidValues() { _selectedEntry = MakeEntry(_ticker); Assert.IsTrue(_entryValidator.IsValidEntry(_selectedEntry, _selectedEntry.Ticker)); } [Test] public void IsValidEntry_WithInValidTicker() { _selectedEntry = MakeEntry(""); Assert.IsFalse(_entryValidator.IsValidEntry(_selectedEntry, _selectedEntry.Ticker)); } }} 

请有人帮忙吗? 谢谢..

使用匿名方法订阅事件可能是最简单的:

 [Test] public void IsValidEntry_WithValidValues() { _selectedEntry = MakeEntry(_ticker); _entryValidator.OnInvalidEntry += delegate { Assert.Fail("Shouldn't be called"); }; Assert.IsTrue(_entryValidator.IsValidEntry(_selectedEntry, _selectedEntry.Ticker)); } [Test] public void IsValidEntry_WithInValidTicker() { bool eventRaised = false; _selectedEntry = MakeEntry(""); _entryValidator.OnInvalidEntry += delegate { eventRaised = true; }; Assert.IsFalse(_entryValidator.IsValidEntry(_selectedEntry, _selectedEntry.Ticker)); Assert.IsTrue(eventRaised); } 

在第二个测试中,您可能希望validation事件参数是否也符合预期。

另请注意,“invalid”是一个单词 – 因此您的测试应该是IsValidEntry_WithInvalidTicker 。 我也不打扰设置 – 我只是在每个测试中声明新的局部变量。

我将重构您的类以使RaiseInvalidEntryEvent成为虚拟,以便可以在您的IsValidEntry_WithInValidTicker中模拟它,然后validation它在票证无效时被调用。

然后我会有另一个测试validationRaiseInvalidEntryEvent分别调用anon委托。

unit testing应该尽可能primefaces,并且您希望在不同的测试中validation这两种行为。

 public delegate void OnInvalidEntryMethod(ITnEntry entry, string message); public class EntryValidator { public event OnInvalidEntryMethod OnInvalidEntry; public bool IsValidEntry(ITnEntry entry, string ticker) { if (!IsFieldValid(entry, ticker.Trim().Length.ToString(), "0")) return false; return true; } private bool IsFieldValid(ITnEntry entry, string actual, string invalidValue) { if (actual == invalidValue) { RaiseInvalidEntryEvent(entry); return false; } return true; } public virtual void RaiseInvalidEntryEvent(ITnEntry entry) { if (OnInvalidEntry != null) OnInvalidEntry(entry, "Invalid entry in list: " + entry.List.Name + "."); } } // Had to reverse engineer the following since they were not available in the question public interface ITnEntry { Ticket List { get; set; } string Ticker { get; set; } } public class TnEntry : ITnEntry { public Ticket List { get; set; } public string Ticker { get; set; } } public class Ticket { public string Name { get; set; } } 

注意:一些OOP evangalists适用于公开而非私有的事情,基本上unit testing和TDD有一些要求纯OOP不一致。 为简单起见,我将RaiseInvalidEntryEvent设为public,但通常我会将其设为内部,然后通过InternalsVisibleTo将程序集暴露给unit testing。 我过去4年来一直在做TDD,很少再使用私有。

unit testing很快(注意,这是使用VS2012的MSTEST框架)

 [TestClass] public class UnitTest1 { #region TestHelpers private ITnEntry MakeEntry(string ticker) { return new TnEntry {Ticker = ticker, List = new Ticket()}; } #endregion [TestMethod] public void IsValidEntry_WithValidValues_ReturnsTrue() { // ARRANGE var target = new EntryValidator(); var selectedEntry = MakeEntry("BOL"); // ACT bool actual = target.IsValidEntry(selectedEntry, selectedEntry.Ticker); // ASSERT Assert.IsTrue(actual); } [TestMethod] public void IsValidEntry_WithInValidTicker_ReturnsFalse() { // ARRANGE var target = new EntryValidator(); var selectedEntry = MakeEntry(""); // ACT bool actual = target.IsValidEntry(selectedEntry, selectedEntry.Ticker); // ASSERT Assert.IsFalse(actual); } [TestMethod] public void IsValidEntry_WithInvalidTicker_RaisesEvent() { // ARRANGE // generate a dynamic mock which will stub all virtual methods var target = Rhino.Mocks.MockRepository.GenerateMock(); var selectedEntry = MakeEntry(""); // ACT bool actual = target.IsValidEntry(selectedEntry, selectedEntry.Ticker); // ASSERT // assert that RaiseInvalidEntryEvent was called target.AssertWasCalled(x => x.RaiseInvalidEntryEvent(Arg.Is.Anything)); } [TestMethod] public void RaiseInvalidEntryEvent_WithValidHandler_CallsDelegate() { // ARRANGE var target = new EntryValidator(); var selectedEntry = MakeEntry(""); bool delegateCalled = false; // attach a handler to set delegateCalled to true target.OnInvalidEntry += delegate { delegateCalled = true; }; // ACT target.IsValidEntry(selectedEntry, selectedEntry.Ticker); // ASSERT Assert.IsTrue(delegateCalled); } } 

您的测试应使用虚方法订阅事件OnInvalidEntry ,调用IsValidEntry并检查结果。