如何使用`using`语句对方法进行unit testing?
如何为具有using语句的方法编写unit testing?
例如,假设我有一个方法Foo
。
public bool Foo() { using (IMyDisposableClass client = new MyDisposableClass()) { return client.SomeOtherMethod(); } }
我怎样才能测试上面的代码?
有时我选择不手动使用using
语句和Dispose()
对象。 我希望有人会告诉我一个我可以使用的技巧。
如果使用工厂(注入父类)而不是使用new关键字IMyDisposable
,则可以模拟IMyDisposable
并对dispose方法调用进行validation。
public bool Foo() { using (IMyDisposableClass client = _myDisposableClassFactory.Create()) { return client.SomeOtherMethod(); } }
如果你已经有了代码并且正在询问如何测试它,那么你就不会先编写测试了……所以不是真的在做TDD。
但是,你在这里有一个依赖。 所以TDD方法是使用dependency injection 。 使用像Unity这样的IoC容器可以更容易。
在“正确”执行TDD时,您的思维过程应在此类场景中运行如下:
- 我需要做一个
Foo
- 为此,我将依赖一个外部依赖,它将实现
IMyDisposableClass
的接口(新的或预先存在的) - 因此,我将
IMyDisposableClass
注入到通过其构造函数声明Foo
的类中
然后你会编写一个(或多个)失败的测试,然后你才会在你编写Foo
函数体的位置,并确定是否需要使用using
块。
实际上你可能知道是的,你将使用一个using
块。 但TDD的一部分原因是,在您(通过测试)certificate需要使用需要此对象的对象之前,您不必担心这一点。
一旦确定需要使用using
块,您就会想要编写一个失败的测试 – 例如使用Rhino Mocks之类的东西设置一个期望Dispose
将在实现IMyDisposableClass
的模拟对象上IMyDisposableClass
。
例如(使用Rhino IMyDisposableClass
来模拟IMyDisposableClass
)。
[TestFixture] public class When_calling_Foo { [Test] public void Should_call_Dispose() { IMyDisposableClass disposable = MockRepository .GenerateMock(); Stuff stuff = new Stuff(disposable); stuff.Foo(); disposable.AssertWasCalled(x => x.Dispose()); } }
存在Foo函数的类,将IMyDisposableClass
作为依赖IMyDisposableClass
注入:
public class Stuff { private readonly IMyDisposableClass _client; public Stuff(IMyDisposableClass client) { _client = client; } public bool Foo() { using (_client) { return _client.SomeOtherMethod(); } } }
和界面IMyDisposableClass
public interface IMyDisposableClass : IDisposable { bool SomeOtherMethod(); }
你的问题没有意义。 如果您使用的是TDD,那么您应该已经对所编写的内容进行了测试。 要求,然后测试,然后设计,然后开发。 您的代码要么通过测试,要么不通过。
现在,如果您的问题是如何对上面的代码进行unit testing,那么这完全是另一个问题,我认为其他海报已经在那里回答了问题。
有时我认为有比开发者更流行的流行语:)
像这样的包装器方法不是单元可测试的,因为您无法指定相关的前置条件或后置条件。
要使方法可测试,您必须将IMyDisposableClass
实例传递给方法或托管Foo
的类(并使主机类本身实现IDisposable
),因此您可以使用测试双重而不是真实的东西来validation任何与之互动。
你的问题没有意义。 如果您正在进行TDD,那么您发布的方法已经过全面测试,否则它首先就不存在了。 所以,你的问题没有意义。
另一方面,如果您发布的方法已经存在,但尚未经过全面测试,那么您无论如何都不会进行TDD,而您对TDD的问题也没有意义。
在TDD中,未经测试的代码根本不可能存在。 期。
如果您正在测试Foo,那么您应该查看Foo的输出,而不是担心它在内部使用的类的处理。
如果你想测试MyDisposableClass
的dispose方法以查看它是否正常工作,那么它应该是针对MyDisposableClass
构建的单独的unit testing。
您不需要对using { }
块进行unit testing,因为这是该语言的一部分。 您要么相信它正在工作,要么不使用C#。 :)我没有看到需要编写unit testing来validation是否正在调用Dispose()
。
没有Foo的规范,我们怎么说如何测试呢?
- 获取Foo的规范。
- 编写测试以确保它满足所有规范和要求(或合理的子集 – 某些function可能需要几乎无限量的数据来测试)。
我相信你在那里有第二个隐含的问题 – 这是如何正确地测试你的MyDisposableClass的使用通过退出using子句释放它时释放对象。 这是一个单独的测试问题,不应与Foo的测试结合,因为Foo的规范不应该引用特定于实现的细节,例如使用MyDisposabeClass。
我认为其他海报已经回答了这个问题,所以我不会进一步阐述。