使用类方法

时间:2018-04-20 06:35:18

标签: objective-c unit-testing dependency-injection

我有一个只有类方法的类

//FileManager.h

+(void)writeData:(NSData*)data toFile:(NSString*)filePath;
//...
//some more class methods

我在另一个中使用这个类

//AttachmentsRepository.m

-(void)newAttachment:(NSData*)attachmentData{
    //some code
    NSString * generatedPath = @"/some/generated/path";
    [FileManager writeData:attachmentData toFile:generatedPath];
}

现在我正在为 AttachmentRepository 编写测试,并想知道如何注入 FileManager

我使用的是“提取和覆盖调用”技术:

//AttachmentsRepository.m

-(void)newAttachment:(NSData*)attachmentData{
    //some code
    NSString * generatedPath = @"/some/generated/path";
    [[self getFileManagerClass] writeData:attachmentData toFile:generatedPath];
}
-(Class)getFileManagerClass{
    return [FileManager class];
}

现在,在我的测试中,我只是将getFileManagerClass存根,以便返回[FakeFileManager class]

什么是更好的解决方案?这是遗留代码,但我们现在正在编写它。应该如何实现 FileManager 依赖。

PS。我想使用假的,因为我想在测试 AttachmentRepository 类时避免写入磁盘。

1 个答案:

答案 0 :(得分:0)

来自Michael C. Feathers的“有效使用遗留代码”我发现了“介绍实例代理”技术。

基本上我们复制了我们需要的方法并使它们成为实例方法。他们的身体只是对类/静态方法的调用。然后我们使用实例类作为构造函数的参数或需要使用它的方法。

//FileManager.h

+(void)writeData:(NSData*)data toFile:(NSString*)filePath;
-(void)writeData:(NSData*)data toFile:(NSString*)filePath;
//...

//FileManager.m
-(void)writeData:(NSData*)data toFile:(NSString*)filePath;{
    [FileManager writeData:data toFile:filePath];
}

AttachmentsRepository

//AttachmentsRepository.m
-(instance) initWithFileManager:(FileManager *)fileManager{
    if(self = [super init]){
     _fileManager = fileManager
    }

    return self;
}

-(void)newAttachment:(NSData*)attachmentData{
    //some code
    NSString * generatedPath = @"/some/generated/path";
    [self.fileManager writeData:attachmentData toFile:generatedPath];
}

结论似乎是 FileManager 类不应该有类/静态方法,而是实例方法,而不是在开始时实现它。

所有这些让我感到尴尬 - 使得类/静态的方法可以在实例级别上进行。