单元测试跟踪状态的类

Jus*_*ony 6 .net c# state unit-testing

我正在抽象一类我的历史跟踪部分,所以它看起来像这样:

private readonly Stack<MyObject> _pastHistory = new Stack<MyObject>();

internal virtual Boolean IsAnyHistory { get { return _pastHistory.Any(); } }

internal virtual void AddObjectToHistory(MyObject myObject)
{
  if (myObject == null) throw new ArgumentNullException("myObject");
  _pastHistory.Push(myObject);
}

internal virtual MyObject RemoveLastObject()
{
  if(!IsAnyHistory) throw new InvalidOperationException("There is no previous history.");
  return _pastHistory.Pop();
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我想单元测试Remove会返回最后添加的对象.

  • AddObjectToHistory
  • RemoveObjectToHistory - >返回放入via的内容 AddObjectToHistory

但是,如果我必须先调用Add,它不是真正的单元测试吗?但是,我可以看到以真正的单元测试方式执行此操作的唯一方法是在构造函数中传递Stack对象或模拟出IsAnyHistory...但是模拟我的SUT也很奇怪.所以,我的问题是,从教条的角度来看,这是一个单元测试吗?如果没有,我该如何清理它...是构造函数注入我唯一的方法?它似乎只是需要传递一个简单的对象?是否可以将这个简单的物体推出注入?

k.m*_*k.m 4

对于这些场景有两种方法:

  1. 干扰设计,例如制作_pastHistory internal/protected或注入堆栈
  2. 使用其他(可能是单元测试的)方法来执行验证

与往常一样,没有黄金法则,尽管我认为您通常应该避免单元测试强制设计更改的情况(因为这些更改很可能会给代码使用者带来歧义/不必要的问题)。

尽管如此,最终还是您必须权衡您希望单元测试代码对设计的干扰程度(第一种情况)或改变完美的单元测试定义(第二种情况)。

通常,我发现第二种情况更有吸引力 - 它不会使原始类代码变得混乱,并且您很可能已经Add测试过 -可以安全地依赖它