简体   繁体   English

C#单元测试委托事件处理程序

[英]c# Unit test a delegate event handler

I have a CountDownTimer class that updates a controller that updates the user interface. 我有一个CountDownTimer类,用于更新更新用户界面的控制器。 The problem i have is when i run my unit tests i get a NllReferenceException because the event handlder(Tick) is never initialized always null. 我遇到的问题是,当我运行单元测试时,我得到了NllReferenceException,因为事件handlder(Tick)从未初始化为空。 What is the best possible solution to this problem? 解决此问题的最佳方法是什么? Or should i go about it differently. 还是我应该以不同的方式去做。 Thanks 谢谢

public class CountDownTimer : ICountDownTimer
{
    private int seconds; // Time in seconds
    private int reSetValue; // Time in seconds
    private System.Windows.Forms.Timer timer1;
    public event TickHandler Tick;
    public EventArgs e = null;
    public delegate void TickHandler(CountDownTimer m, EventArgs e, int seconds);

    public CountDownTimer(int seconds)
    {
        this.seconds = seconds;
        reSetValue = seconds;

        timer1 = new System.Windows.Forms.Timer();
        timer1.Tick += new EventHandler(timer1_Tick); // Add Handler(timer1_Tick)
        timer1.Interval = 1000; // 1 second
     }

    private void timer1_Tick(object sender, EventArgs e)
    {
        CallTickHandler();

        if (getSeconds() == 0) // Stop Timer at 0
        {
            timer1.Stop(); // Stop timer
        }
        else
        {
            if (getSeconds() % 60 == 0 || getSeconds() >= 1 && getSeconds() <= 10)
            {
                CallTickHandler();
            }
        }
        seconds--; // Decrement seconds
    }

    public void StartTimer()
    {
        timer1.Start();
    }

    public void StopTimer()
    {
        timer1.Stop();
    }

    public void ResetTimer()
    {
        timer1.Stop();
        seconds = reSetValue;
        CallTickHandler();
    }

    public void SetTimer(int seconds)
    {
        timer1.Stop();
        this.seconds = getSeconds();
        reSetValue = getSeconds();
        CallTickHandler();
    }

    internal void CallTickHandler()
    {
        Tick(this, e, getSeconds());
    }

    public Boolean isEnabled()
    {
        return timer1.Enabled;
    }

    public int getSeconds()
    {
        return seconds;
    }
}


public class Controller : ApplicationContext
{
    //Store a reference to the UI
    internal frmMain MainUI { get; set; }
    private int seconds = 300;
    CountDownTimer timer;

    public Controller()
    {
        MainUI = new frmMain(this);

        //We can do any necessary checks or changes to the MainUI here before it becomes visible
        MainUI.Show();
        timer = new CountDownTimer(seconds);
        SubscribeToTickListener(timer);
        TickUpdate(seconds);
    }

    internal void TickUpdate(string seconds)
    {
        MainUI.lblTimer.Text = ("" + Convert.ToInt32(seconds) / 60).PadLeft(2, '0') + "m:" + ("" + Convert.ToInt32(seconds) % 60).PadLeft(2, '0') + "s";
    }

    internal void TickUpdate(int seconds)
    {
        MainUI.lblTimer.Text = ("" + seconds / 60).PadLeft(2, '0') + "m:" + ("" + seconds % 60).PadLeft(2, '0') + "s";
        if (seconds <= 10)
        {
            //ss.Speak(seconds.ToString());
        }
        else
        {
            //ss.Speak((seconds / 60).ToString() + " minute warning");
        }
    }

    internal void StartTimer()
    {
        timer.StartTimer();
    }

    internal void ResetTimer()
    {
        timer.ResetTimer();
    }

    internal void StopTimer()
    {
        timer.StopTimer();
    }

    internal void SetTimer(int seconds)
    {
        timer.SetTimer(seconds);
    }

    public void SubscribeToTickListener(CountDownTimer cdt)
    {
        cdt.Tick += new CountDownTimer.TickHandler(TickMsgRecieved);
    }
    public void TickMsgRecieved(CountDownTimer cdt, EventArgs e, int seconds)
    {
        TickUpdate(seconds);
        TickUpdate(seconds.ToString());
    }
}


public class CountDownTimerTests
{

    private CountDownTimer t = new CountDownTimer(300);

    [TestMethod()]
    public void CountDownTimerTest()
    {
        CountDownTimer t = new CountDownTimer(300);
    }

    [TestMethod()]
    public void StartTimerTest()
    {
        //CountDownTimer t = new CountDownTimer(300);
        t.StartTimer();
        Boolean expected = t.isEnabled();
        Boolean actual = true;
        Assert.AreEqual(expected, actual);
     }

    [TestMethod()]
    public void StopTimerTest()
    {
        //CountDownTimer t = new CountDownTimer(300);
        t.StartTimer();
        t.StopTimer();
        Boolean expected = t.isEnabled();
        Boolean actual = false;
        Assert.AreEqual(expected, actual);
    }

    [TestMethod()]
    public void ResetTimerTest()
    {
        int expected = t.getSeconds();
        t.ResetTimer();
        int actual = t.getSeconds();
        Assert.AreEqual(expected, actual);
    }

    [TestMethod()]
    public void SetTimerTest()
    {
        int expected = t.getSeconds();
        t.SetTimer(120);
        int actual = t.getSeconds();
        Assert.AreEqual(expected, actual);
    }
}

In this case you can probably use a mock implementation of the event. 在这种情况下,您可能可以使用事件的模拟实现。 I would add the following mock event to your test class to simulate a consumer of the CountDownTimer class. 我将以下模拟事件添加到您的测试类中,以模拟CountDownTimer类的使用者。

    [TestInitialize]
    public void TestSetup()
    {
        t.Tick += new CountDownTimer.TickHandler(MockTickEvent);
    }
    [TestCleanup]
    public void TestCleanup()
    {
        t.Tick -= MockTickEvent;
    }
    void MockTickEvent(CountDownTimer m, EventArgs e, int seconds)
    {
        ///you may need to add further test code here to fully cover your code
        return;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM