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