有关单元测试的问题

时间:2019-02-13 02:37:08

标签: c# unit-testing

最近,我正在学习单元测试,并尝试在我的项目中使用此技能。 但是,我对如何测试以下代码有一些疑问。

 public class Class1
{
    private Timer _timer = new Timer();

    public Class1()
    {
        _timer.Interval = 1000;
        _timer.Elapsed += _timer_Elapsed;
    }

    private void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        //some works
    }

    public void start()
    {
        _timer.Start();
        //some works

    }
    public void stop()
    {
        _timer.Stop();
        //some works
    }
}

我真的不知道如何在不破坏其封装的情况下测试此类。

我应该公开'_timer_Elapsed'方法吗?如果埃文这样做,那么下一个问题是如何测试方法“开始”和“停止”。我是否应该使用存根对象替代Timer以便测试此类?如果那样的话,该类将太复杂,因为我需要创建一个接口,并创建一个封装Timer并实现上述接口的类。

public interface IEncal
{
    double Interval { get; set; }
    event ElapsedEventHandler Elapsed;
    void Stop();
    void Start();
}
public class MyClass : IEncal
{
    Timer timer = new Timer();
    public double Interval { get { return timer.Interval; } set { timer.Interval = value; } }

    public event ElapsedEventHandler Elapsed
    {
        add { timer.Elapsed += value; }
        remove { timer.Elapsed -= value; }
    }

    public void Start()
    {
        timer.Start();
    }

    public void Stop()
    {
        timer.Stop();
    }
}
public class Class1
{
    private IEncal _timer;

    public Class1(IEncal timer)
    {
        _timer = timer;
        _timer.Interval = 1000;
        _timer.Elapsed += _timer_Elapsed;
    }

    public void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        //some works
    }

    public void start()
    {
        _timer.Start();
        //some works
    }
    public void stop()
    {
        _timer.Stop();
        //some works
    }
}

有没有更好的方法来测试此类?


以下是我使用的真实代码。 我已经为ISender类和IInfoProducer类编写了单元测试。 由于这是我第一次使用单元测试,因此我想考虑一下每个要学习的课程。

回到问题所在,此类基本上是一个Timer类。在流失时, 它发送一个信息。那么我应该如何测试此定时发送过程?

public class InfomationSender
{
    private readonly Timer _timer = new Timer();
    private readonly ISender _sender;
    private readonly IInfoProducer _producer;

    public InfomationSender(ISender sender, IInfoProducer producer)
    {
        _sender = sender;
        _producer = producer;
        _timer.Interval = 1000;
        _timer.Elapsed += _timer_Elapsed;
    }

    private void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        var info = _producer.getInfo();
        _sender.send(info);

    }

    public void start()
    {
        _timer.Start();

    }
    public void stop()
    {
        _timer.Stop();
        _sender.Dispose();
    }
}

1 个答案:

答案 0 :(得分:1)

您应该能够测试类而不进行模拟。减少嘲笑会更有价值。 但是您没有提供有关代码在// some works区域中所做的工作的信息。因为这是您要测试的内容,所以计时器只是实现细节。

对于测试“某些作品”类,应该提供对“某些作品”结果的一些公共访问,否则结果将通过注入的依赖项(存储库,记录器等)“公开”

假设类将每秒执行“一些工作”,并在调用Result方法之后更新Stop属性。

public class LiveCalculator
{
    private readonly Timer _timer;
    private List<int> _allValues
    private int _lastSum;

    public int LastSum => _lastSum;

    public LiveCalculator()
    {
        _allValues = new List<int>();
        _timer = new Timer { Interval = 1000 };
        _timer.Elapsed += _timer_Elapsed;
    }

    private void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        _allValues.Add(42);
    }

    public void start()
    {
        _timer.Start();            
    }

    public void stop()
    {
        _timer.Stop();
        _lastResult = _allValues.Sum();
    }
}

测试

[Fact]
public async Task AfterFiveSeconds_LastResultEquals210()
{
    var calculator = new LiveCalculator();

    calculator.Start();        
    await Task.Delay(5100);
    calculator.Stop();

    calculator.LastResult.Should().Be(210);
}