78 .net c# tdd inversion-of-control
我已经开始了很长时间的艰苦探索,学习并将TDD 应用到我的工作流程中.我认为TDD与IoC原理非常吻合.
在SO中浏览了一些TDD标记问题之后,我认为对接口而不是对象进行编程是一个好主意.
您能提供简单的代码示例,说明这是什么,以及如何在实际使用案例中应用它?简单的例子对我(以及其他想要学习的人)掌握概念至关重要.
非常感谢.
Bil*_*eal 82
考虑:
class MyClass
{
//Implementation
public void Foo() {}
}
class SomethingYouWantToTest
{
public bool MyMethod(MyClass c)
{
//Code you want to test
c.Foo();
}
}
Run Code Online (Sandbox Code Playgroud)
因为MyMethod只接受一个MyClass,如果你想MyClass用模拟对象替换以便进行单元测试,你就不能.更好的是使用界面:
interface IMyClass
{
void Foo();
}
class MyClass : IMyClass
{
//Implementation
public void Foo() {}
}
class SomethingYouWantToTest
{
public bool MyMethod(IMyClass c)
{
//Code you want to test
c.Foo();
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以测试MyMethod,因为它只使用一个接口,而不是一个特定的具体实现.然后,您可以实现该接口以创建您想要用于测试目的的任何类型的模拟或伪造.甚至还有像Rhino Mocks这样的库Rhino.Mocks.MockRepository.StrictMock<T>(),可以使用任何界面并在运行中构建一个模拟对象.
hos*_*ude 18
这完全是亲密的问题.如果您编写一个实现(一个已实现的对象),那么作为它的消费者,您与该"其他"代码处于非常亲密的关系中.这意味着你必须知道如何构造它(即它有什么依赖关系,可能是构造函数params,可能是setter),什么时候处理它,如果没有它你可能做不了多少.
实现对象前面的界面可以让你做一些事情 -
**更新**有人要求提供IOC容器(工厂)的示例.几乎所有平台都有很多,但在它们的核心,它们的工作方式如下:
您在应用程序启动例程中初始化容器.一些框架通过配置文件或代码或两者来实现.
您"注册"您希望容器为其创建的实现作为它们实现的接口的工厂(例如:为Service接口注册MyServiceImpl).在此注册过程中,通常会提供一些行为策略,例如每次创建新实例或使用单个(吨)实例
当容器为您创建对象时,它会将任何依赖项作为创建过程的一部分注入到这些对象中(即,如果您的对象依赖于另一个接口,则依次提供该接口的实现,依此类推).
伪编码它看起来像这样:
IocContainer container = new IocContainer();
//Register my impl for the Service Interface, with a Singleton policy
container.RegisterType(Service, ServiceImpl, LifecyclePolicy.SINGLETON);
//Use the container as a factory
Service myService = container.Resolve<Service>();
//Blissfully unaware of the implementation, call the service method.
myService.DoGoodWork();
Run Code Online (Sandbox Code Playgroud)
对接口进行编程时,您将编写使用接口实例的代码,而不是具体类型.例如,您可以使用以下模式,其中包含构造函数注入.构造函数注入和控制反转的其他部分不需要能够针对接口进行编程,但是因为您从TDD和IoC的角度来看,我已经通过这种方式连接它以给您一些上下文,希望熟悉.
public class PersonService
{
private readonly IPersonRepository repository;
public PersonService(IPersonRepository repository)
{
this.repository = repository;
}
public IList<Person> PeopleOverEighteen
{
get
{
return (from e in repository.Entities where e.Age > 18 select e).ToList();
}
}
}
Run Code Online (Sandbox Code Playgroud)
存储库对象是传入的,是一种接口类型.传入接口的好处是能够在不改变用法的情况下"换出"具体实现.
例如,人们会假设在运行时IoC容器将注入一个连接到数据库的存储库.在测试期间,您可以传入模拟或存根存储库来练习您的PeopleOverEighteen方法.
| 归档时间: |
|
| 查看次数: |
18557 次 |
| 最近记录: |