【问题标题】:Is there any way to emulate user's input in XCTest function?有没有办法在 XCTest 函数中模拟用户的输入?
【发布时间】:2020-07-02 18:26:02
【问题描述】:

我的方法需要用户输入

@implementation TeamFormation
- (void)run {
    NSFileHandle *kbd = [NSFileHandle fileHandleWithStandardInput];
    NSData *inputData = [kbd availableData];
    NSString *option = [[[NSString alloc] initWithData:inputData
                     encoding:NSUTF8StringEncoding] substringToIndex:1];
    NSLog(@"%@",option);
}
@end

那我想通过一个测试用例来覆盖这个方法

@interface TeamFormationTests : XCTestCase

@end

@implementation TeamFormationTests

- (void)testTeamFormation {
    TeamFormation *teamFormation = [TeamFormation new];
    [teamFormation run];

    // emulate user's input here
}

@end

那么,如何在测试用例函数中模拟用户输入?

【问题讨论】:

    标签: objective-c unit-testing user-input xctest nsfilehandle


    【解决方案1】:

    您有很多选择来实现这一目标。下面两个很明显。

    更改 run 以接受参数

    • - (void)run- (void)runWithFileHandle:(NSFileHandle *)handle
    • 您的应用代码可以传递标准输入文件句柄
    • 您的测试代码可以将句柄传递给具有所需输入的文件

    用协议模拟它

    创建DataProvider协议:

    @protocol DataProvider
    
    @property(readonly, copy) NSData *availableData;
    
    @end
    

    使NSFileHandle符合此协议:

    @interface NSFileHandle (AvailableDataProvider) <DataProvider>
    @end
    

    TeamFormation上存储一个实现此协议的对象:

    @interface TeamFormation : NSObject
    
    @property (nonatomic, nonnull, strong) id<DataProvider> dataProvider;
    
    - (NSString *)run;
    
    @end
    

    默认使用标准输入文件句柄:

    @implementation TeamFormation
    
    - (instancetype)init {
        if ((self = [super init]) == nil) {
            return nil;
        }
        
        _dataProvider = [NSFileHandle fileHandleWithStandardInput];
        return self;
    }
    
    - (NSString *)run {
        NSData *inputData = [self.dataProvider availableData];
        return [[[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding] substringToIndex:1];
    }
    
    @end
    

    在您的测试中创建TestDataProvider

    @interface TestDataProvider: NSObject<DataProvider>
    
    @property (nonatomic, strong, nonnull) NSData *dataToProvide;
    
    @end
    
    @implementation TestDataProvider
    
    - (instancetype)init {
        if ((self = [super init]) == nil) {
            return nil;
        }
        
        _dataToProvide = [NSData new];
        
        return self;
    }
    
    - (NSData *)availableData {
        return _dataToProvide;
    }
    
    @end
    

    并在TestFormationTests中使用它:

    @implementation TeamFormationTests
    
    - (void)testFormationRun {
        TestDataProvider *dataProvider = [TestDataProvider new];
        TeamFormation *formation = [TeamFormation new];
        formation.dataProvider = dataProvider;
        
        XCTAssertThrows([formation run]);
        
        dataProvider.dataToProvide = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
        XCTAssertEqualObjects([formation run], @"f");
        
        dataProvider.dataToProvide = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
        XCTAssertEqualObjects([formation run], @"b");
    }
    
    @end
    

    【讨论】:

    • 谢谢!很酷的答案!
    猜你喜欢
    • 1970-01-01
    • 2017-09-02
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 2022-07-25
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    相关资源
    最近更新 更多