抽取接口使底层实现可替换
首先将第一章的代码重构,抽取出实现代码,放到FileExtensionManager类中。
- public class LogAnalyzer
- {
- public bool WasLastFileNameValid { get; set; }
- public bool IsValidLogFileName(string fileName)
- {
- //使用抽取出来的类
- FileExtensionManager mgr =
- new FileExtensionManager();
- return mgr.IsValid(fileName);
- }
- }
- //首先定义出这个抽取的类
- class FileExtensionManager
- {
- public bool IsValid(string fileName)
- {
- //读取文件
- }
- }
然后定义ExtensionManager的接口IExtensionManager并实现
- class FileExtensionManager:IExtensionManager
- {
- public bool IsValid(string fileName)
- {
- //读取文件
- }
- }
- //然后定义新接口
- public interface IExtensionManager
- {
- bool IsValid(string fileName);
- }
- public bool IsValidLogFileName(string fileName)
- {
- //定义这个接口的类型变量
- IExtensionManager mgr =
- new FileExtensionManager();
- return mgr.IsValid(fileName);
- }
现在就创建了一个提供IsValid(string)方法的接口IExtensionManager,用FileExtensionManager实现这个接口。代码功能没有变,但是现在可以用自己的伪造的扩展名管理器来代替真实 扩展名管理器了
- //这个是总是返回true的简单桩代码
- //使用Fake说明这个类的对象类似另一个对象,既可能用作模拟对象,也可能用作桩
- public class AlwaysValidFakeExtensionManager: IExtensionManager
- {
- //实现IExtensionManager接口
- public bool IsValid(string fileName)
- {
- return true;
- }
- }
现在虽然有了一个接口和两个实现此接口的类,但是被测试的方法还是对具体类进行直接调用。
- public bool IsValidLogFileName(string fileName)
- {
- IExtensionManager mgr =
- new FileExtensionManager();
- return mgr.IsValid(fileName);
- }
所以必须想办法让被测试的方法调用伪对象,而不是IExtensionManager的原本实现,因此需要在代码中引入一个接缝,然后插入桩。
依赖注入:在被测试单元中注入一个伪实现
参数注入
给方法签名添加一个参数,从而给这个方法传入一个(伪造的)依赖实例
- Method(string,int,FakeClass)
- //其中FakeClass就是注入的依赖实例。