C# 创建在自定义模拟类中返回IDisposable的方法
我试图教育一些人使用真正的单元测试,因为他们的大多数自动化测试都是集成测试 为了做到这一点,我想重构一个类,这样我就可以在没有依赖关系的情况下单独测试它 为此,我有以下限制:C# 创建在自定义模拟类中返回IDisposable的方法,c#,unit-testing,C#,Unit Testing,我试图教育一些人使用真正的单元测试,因为他们的大多数自动化测试都是集成测试 为了做到这一点,我想重构一个类,这样我就可以在没有依赖关系的情况下单独测试它 为此,我有以下限制: 1.我无法使用任何模拟框架,因此我必须为此创建自定义模拟。 2.我无法修改将被模拟的类以将任何私有方法更改为受保护的或公共的,或将方法更改为虚拟的,因此我无法从此类继承并重写这些方法。 因此,在我要测试的方法中,我有以下using语句: using(myObject.CreateScope()) { ..
1.我无法使用任何模拟框架,因此我必须为此创建自定义模拟。
2.我无法修改将被模拟的类以将任何私有方法更改为受保护的或公共的,或将方法更改为虚拟的,因此我无法从此类继承并重写这些方法。 因此,在我要测试的方法中,我有以下using语句:
using(myObject.CreateScope())
{
.... do something
}
到目前为止,我计划做的是:1.从myObject的类中提取接口。
2.使用属性在SUT上注入接口 当然,“CreateScope”方法将是接口的一部分,其定义如下:
public IDisposable CreateScope();
因此,在我的自定义模拟中,我想做如下操作:
public IDisposable CreateScope()
{
return new AnyDisposableObject();
}
我的问题是:
考虑到隔离测试类提供了集成测试无法提供的许多好处,在定制模拟中实现“CreateScope”方法最简单、最清晰的方法是什么
我是否应该创建一个空的伪对象,其唯一目的是实现IDisposable?我应该使用.Net framework中实现IDisposable的任何对象吗?
有没有比上述两种选择更好的方法 提前谢谢 更新:为了清晰起见
using(myObject.CreateScope())
{
var local = parameter.Where(o => !myObject.Contains(o)).Select(o).ToList();
...
myObject.Register(newInstance);
...
return myObject.GetList();
}
我将测试“using”语句中的逻辑。当调用返回myObject对象的方法或空方法返回空方法时,myObject对象将被模拟以提供值。CreateScope方法所做的是在受保护的字典中放置一个锁,但我不想用它来测试该功能
希望这能澄清意图。尝试以下实现IDisposable的模拟对象:
class MockDisposable : IDisposable
{
bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_disposed) // only dispose once!
{
if (disposing)
{
// Not in destructor, OK to reference other objects
}
// perform cleanup for this object
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
// tell the GC not to finalize
GC.SuppressFinalize(this);
}
~MockDisposable()
{
Dispose(false);
}
}
你为什么要施加这些限制?您所建议的实际上并不是单元测试;如果我没有看错你的问题,你实际上是在代码中覆盖不同的行为。这些限制是为了证明你可以在不影响原始架构的情况下添加单元测试,并解释模拟框架在幕后的作用。请记住,我将努力解决“害怕改变”的问题:)您能提供一个您希望制作的代码示例吗?例如,在单元测试中,您想在类a上测试方法B的输出。您会这样做吗<代码>使用(var instance=classAInstance.CreateScope()){var result=instance.MethodB(x,y,z);Assert.AreEqual(result,“SomeResult”);})?所以我猜答案是“创建一个伪对象,其唯一目的是实现IDisposable”。很公平:)非常感谢你的回答,它非常有效。@Sergio:是的,那就是答案。实际上,您可以只实现Dispose()方法而不执行任何操作来创建一个更原始的模拟IDisposable对象,但这是一个实现良好的Dispose对象。祝你好运!!仅供参考,~Testing()应该是~mock。您的终结器有一个输入错误。