用于测试类的依赖注入

问题描述 投票:0回答:1

我想为单例类MySingleton编写测试

MySingletone.h:

@interface MySingleton : NSObject

@property (class, readonly, strong) Class_B* shared;

@end

MySingleton.m:

@interface MySingleton()
{
    SomeClass* _someClass;
}

@end

@implementation MySingletone

+ (MySingleton*)shared {
    static MySingleton* mySingleton;
    static dispatch_once_t predicate;

    dispatch_once(&predicate, ^{
        SomeClass* someClass = [[SomeClass alloc] init];
        mySingleton = [[MySingleton alloc] initWithSomeClass:someClass];
    });

    return mySingleton;
}

- (instancetype)initWithSomeClass:(SomeClass*)someClass {
    self = [super init];
    if (self) {
        _someClass = someClass;
    }
    return self;
}

@end

在测试中,我希望能够用假的替换具体的SomeClass,所以我定义了一个SomeClass应符合的协议:

@protocol SomeProtocol
@end

@interface SomeClass : NSObject <SomeProtocol>
@end

@interface MySingleton : NSObject
{
  id<SomeProtocol> _someClass;
}
@property (class, readonly, strong)MySingleton* shared;

- (instancetype)initWithSomeClass:(id<SomeProtocol>)someClass;
@end

@implementation MySingleton

+ (MySingleton*)shared {

  static MySingleton* mySingleton;
  static dispatch_once_t predicate;

  dispatch_once(&predicate, ^{
    SomeClass* someClass = [[SomeClass alloc] init];
    mySingleton = [[MySingleton alloc] initWithSomeClass:someClass];
  });

  return mySingleton;
}

- (instancetype)initWithSomeClass:(id<SomeProtocol>)someClass {
  self = [super init];
  if (self) {
    _someClass = someClass;
  }
  return self;
}
@end

现在在我的测试中我定义了一个假类:

@interface someClassFake : NSObject <SomeProtocol>
@end

用它初始化MySingleton

SomeClassFake* someFakeClass = [[SomeClassFake alloc] init];
MySingletone* mySingleton = [[MySingleton alloc] initWithObject: someClassFake];

我留下的唯一问题是,在测试套装中,虽然我没有使用具体的SomeClass,但我仍然依赖它,因为它被用在shared getter中,链接器将要求我为它提供实现。什么是最好的设计解决方案,以便我的测试服不依赖于SomeClass

objective-c unit-testing testing dependency-injection dependencies
1个回答
0
投票

我想出的最佳解决方案是将shared getter移动到一个类别:

MySingletone + Shared.h:

@interface MySingleton (Shared)
@property (class, readonly, strong)MySingleton* shared;
@end

MySMySingletone + Shared.m:

@implementation MySingleton (Shared)

+ (MySingleton*)shared {

  static MySingleton* mySingleton;
  static dispatch_once_t predicate;

  dispatch_once(&predicate, ^{
    SomeClass* someClass = [[SomeClass alloc] init];
    mySingleton = [[MySingleton alloc] initWithSomeClass:someClass];
  });

  return mySingleton;
}
@end

而现在,在实际代码中导入MySingletone + Shared.h而不是MySingletone.h

© www.soinside.com 2019 - 2024. All rights reserved.