技术开发 频道

我的TDD实践:可测试性驱动开发

  我又想测试GetConverter方法了,怎么办?那就还是把GetConverter这部分逻辑从外部注入吧——哎,难道还要我写一个IConverterFactory接口和ConverterFactory类吗?也不一定,我们还是用“轻量”些的方法吧:

  public class SearchCriteriaBinder : IModelBinder

  {

  ...

  public SearchCriteriaBinder()

  : this(new Tokenizer(), GetConverter) { }

  internal SearchCriteriaBinder(ITokenizer tokenizer, Func converterGetter)

  {

  this.m_tokenizer = tokenizer; this.m_getConverter = converterGetter;

  }

  private readonly ITokenizer m_tokenizer;

  private readonly Func m_getConverter;

  internal static IConverter GetConverter(string field)

  {

  // 使用if ... else或是字典

  }

  private SearchCriteria Build(List tokenGroups)

  {

  ...

  if (fieldTokens.TryGetValue("keywords", out values))

  {

  searchCriteria.Keywords = (string)this.m_getConverter("keywords").Convert(values);

  }

  ...

  }

  }

  这一次,我使用了委托对象的方式注入一段逻辑,它其实也是我们可以使用的一种方式。这样,我们便可以为GetConverter方法作独立的单元测试了。不过,我这里使用委托也有点“展示”的意味在里面,在实际开发过程中,可能我还是会使用ConverterFactory,这对我来说更“正规”一些。这种“接口”与“实现”分离的做法,除了能够独立测试之外,还有一个目的就是为了在测试Build方法时不依赖GetConverter的实现,也意味着不依赖PriceRangeConverter,KeywordConverter的实现等等,因为我们在测试Build方法时,可以提供一个针对测试的GetConverter方法逻辑,返回一些IConverter的Mock或Stub对象。这样,Build方法也就非常独立,不依赖外部实现了。

0
相关文章