7

我是测试新手,请帮忙。

我有以下课程

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));
    }
}}

请问有人可以帮忙吗?谢谢..

4

3 回答 3

12

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

[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);
}

在第二个测试中,您可能想要验证事件参数是否也符合预期。

另请注意,“无效”是一个词 - 所以你的测试应该是IsValidEntry_WithInvalidTicker. 我也不会为设置而烦恼——我只需在每个测试中声明新的局部变量。

于 2013-05-08T20:05:16.683 回答
2

我将重组您的课程以使 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 将程序集公开给单元测试。在过去的 4 年里,我一直在做 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);
    }
}
于 2014-03-10T20:38:14.323 回答
1

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

于 2013-05-08T20:06:47.350 回答