[英]unit testing a class with event and delegate
我是测试新手,请帮忙。
我有以下课程
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);
}
在第二个测试中,您可能想验证事件参数是否也与预期一样。
另请注意,“ invalid”是一个单词-因此您的测试应为IsValidEntry_WithInvalidTicker
。 我也不会打扰安装程序-我只是在每个测试中声明新的局部变量。
我将重组您的类以使RaiseInvalidEntryEvent虚拟,以便可以在IsValidEntry_WithInValidTicker中对其进行模拟,然后验证票证无效时是否调用了它。
然后,我将进行另一个测试,以验证RaiseInvalidEntryEvent分别称为匿名委托。
单元测试应该尽可能地原子,并且您需要在不同的测试中验证这两种行为。
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宣传人员适合于将事物宣布为公开而非私有的情况,基本上,单元测试和TDD对纯OOP有一些要求。 为了简单起见,我将RaiseInvalidEntryEvent公开,但是通常我将其设置为内部,然后通过InternalsVisibleTo将程序集暴露给单元测试。 我过去四年来一直在做TDD,现在很少使用private了。
单元测试很快就会成为(注意,这是使用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<EntryValidator>();
var selectedEntry = MakeEntry("");
// ACT
bool actual = target.IsValidEntry(selectedEntry, selectedEntry.Ticker);
// ASSERT
// assert that RaiseInvalidEntryEvent was called
target.AssertWasCalled(x => x.RaiseInvalidEntryEvent(Arg<ITnEntry>.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
并检查结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.