如何使用`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的规范,我们怎么说如何测试呢?

  1. 获取Foo的规范。
  2. 编写测试以确保它满足所有规范和要求(或合理的子集 – 某些function可能需要几乎无限量的数据来测试)。

我相信你在那里有第二个隐含的问题 – 这是如何正确地测试你的MyDisposableClass的使用通过退出using子句释放它时释放对象。 这是一个单独的测试问题,不应与Foo的测试结合,因为Foo的规范不应该引用特定于实现的细节,例如使用MyDisposabeClass。

我认为其他海报已经回答了这个问题,所以我不会进一步阐述。