.NET 单元测试

.NET单元测试(二):入门

2018-04-09  本文已影响0人  Johnny_

基于状态测试

  在上一篇文章中,我们举了一个带返回值的例子,那么无返回值的情况下又该怎样写单元测试呢?

有如下代码:

public IList<string> Names = new List<string>();
  
public void Reset()
{
    Names.Clear();
}

我们发现,Reset方法内部执行的是Names列表的清空操作,这个操作可以抽象成对被测试类状态的更改,要验证状态更改是否符合预期,我们只需要验证更改前后是否符合预期即可。在这里,只需要测试Reset方法是否按照我们预期的把Names清空即可。如下:

/// <summary>
/// 条件:Names不为空
/// 预期:清空Names
/// </summary>
[TestMethod()]
public void ResetTest_NamesNotEmpty_NamesEmpty()
{
   //Arrange
   var document = new Document();
   document.Names.Add("name0");
   document.Names.Add("name1");

   //Action
   document.Reset();

   //Assert
   Assert.AreEqual(document.Names.Count, 0);
}

依赖外部对象的测试

  单元测试需要能够快速独立运行,隔离掉对外部的依赖是非常必要的,比如文件系统、硬件数据、web服务等。

如下代码:

///<summary>
/// 判断当前字符串是否是合法的html字符串
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public bool IsValidHtml(string input)
{
    var textService = new TextService();
 
    return textService.IsValidHtml(input);
}

可以看到,当前方法依赖TextService来验证html,但是在运行单元测试时,TextService的状态是未知的,它甚至可能还未开发完成。因此,需要隔离掉对TextService的依赖。

而TextService是在IsValidHtml方法内部创建的,我们无法隔离,这个时候就需要对方法进行一系列的修改,以使得它达到可测试的要求(这就是所谓的单元测试约束设计)。

再进一步的分析,可以发现依赖的是TextService提供的IsValidHtml()方法,而并非TextService这个对象,这就好说了,让IsValidHtml()依赖可以提供html验证的接口,我们就可以不用依赖TextService这个对象了,我们抽取接口:

public interface ITextService
{
    bool IsValidHtml(string input);
}

这样我们就可以从对具体实现的依赖解耦为对接口的依赖,因此,在测试方法中我们可以很方便的用一个假的ITextService的实现来替代真实的TextService,由此隔离对真实外部服务的依赖。

这个假的ITextService的实现我们称为 伪对象

如下SubTextService就是我们的伪对象:

public class SubTextService : ITextService
{
    private bool _isValidHtml;
 
    public void SetIsValidHtml(bool value)
    {
        _isValidHtml = value;
    }
 
    public bool IsValidHtml(string input)
    {
        return _isValidHtml;
    }
}

有了伪对象,怎么使用起来呢?

接下来介绍几种伪对象注入的方式

  写单元测试可以为我们的代码增加一层保护,在设计程序时考虑单元测试也可以优化我们的设计,好处多多,何乐而不为呢(●'◡'●)



2017-3-17 23:29:07

上一篇 下一篇

猜你喜欢

热点阅读