C# 单元测试跟踪状态的类
我正在抽象我的一个类的历史跟踪部分,因此它看起来像这样:C# 单元测试跟踪状态的类,c#,.net,unit-testing,state,C#,.net,Unit Testing,State,我正在抽象我的一个类的历史跟踪部分,因此它看起来像这样: private readonly Stack<MyObject> _pastHistory = new Stack<MyObject>(); internal virtual Boolean IsAnyHistory { get { return _pastHistory.Any(); } } internal virtual void AddObjectToHistory(MyObject myObject)
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();
}
private readonly堆栈_pastHistory=new Stack();
内部虚拟布尔值IsAnyHistory{get{return _pastHistory.Any();}
内部虚拟void AddObjectToHistory(MyObject MyObject)
{
如果(myObject==null)抛出新的ArgumentNullException(“myObject”);
_过去的历史。推(myObject);
}
内部虚拟MyObject RemovelAsObject()
{
如果(!IsAnyHistory)抛出新的InvalidOperationException(“没有以前的历史记录”);
return_pastHistory.Pop();
}
我的问题是,我想单元测试Remove将返回最后添加的对象
AddObjectToHistory
->返回通过RemoveObjectToHistory
AddObjectToHistory
然而,如果我必须先调用Add,那么这不是真正的单元测试?但是,我能看到的以真正的单元测试方式实现这一点的唯一方法是在构造函数中传递堆栈对象或模拟
IsAnyHistory
…但是模拟我的SUT也是很奇怪的。所以,我的问题是,从教条的观点来看,这是一个单元测试吗?如果没有,我该如何清理它…这是我唯一的方法吗?在一个简单的物体中,这看起来像是一个拉伸?把这个简单的对象推出来注射可以吗?我认为这仍然是一个单元测试,假设MyObject是一个简单的对象。我经常构造单元测试方法的输入参数
我使用:
在以下情况下,测试不是单元测试:
- 它与数据库通信
- 它通过网络进行通信
- 它涉及到文件系统
- 它不能与任何其他单元测试同时运行
- 您必须对您的环境执行特殊操作(例如编辑配置文件)才能运行它
我认为您试图对单元测试的定义过于具体。您应该测试类的公共行为,而不是具体的实现细节
从代码片段来看,您真正需要关心的是a)调用AddObjectToHistory是否会导致IsAnyHistory返回true,b)RemovelAsObject是否最终会导致IsAnyHistory返回false 对于这些场景,有两种方法:
\u过去历史
内部
/受保护
或注入堆栈通常,我觉得第二种情况更吸引人——它不会扰乱原始类代码,而且您很可能已经测试了
Add
。如其他答案中所述,我认为您的选项可以这样分解
我的2美分。。。客户如何知道删除是否有效?“客户机”应该如何与该对象交互?客户端是否要将堆栈推送到历史跟踪器?将测试视为测试对象的另一个用户/消费者/客户。。使用与实际生产中完全相同的交互。 我还没有听说过任何规则规定不允许对测试对象调用多个方法 要进行模拟,堆栈不是空的。我会打电话给99%的客户。我不会破坏那个物体的封装。。像对待人一样对待对象(我想我在对象思考中读到了这一点)。告诉他们做点什么。。不要闯进来 e、 如果你想让某人钱包里有一些钱
- 简单的方法是给他们钱,让他们自己把钱放进钱包里李>
- 扔掉他们的钱包,塞进他们口袋里的钱包
我希望我在这里没有表现得太强。。看到对象API被“为了可测试性而扭曲”到不再像“可以工作的最简单的事情”的地步,我感到很痛苦 Hrmmm,但我的问题是,为了测试我的实际工作单元,我必须依赖其他工作单元(
AddObjectToHistory
)。所以,我觉得这更像是一个单元测试。如果add-ever发生变化,那么我的remove测试将失败,因此它会使测试对另一个单元变得脆弱…我可以看到双方真的…jus