我已经以编程方式编写了以下按钮:
self.button = [[UIButton alloc] init];
[self.button setTitle:@"Reverse String!" forState:UIControlStateNormal];
self.button.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0];
self.button.layer.cornerRadius = 5.0;
[self.button addTarget:self action:@selector(reverseString:) forControlEvents:UIControlEventTouchUpInside];
但是,当我尝试测试时,我的单元测试失败了:
-(void)testButtonActionAssigned
{
XCTAssert([self.vc.button respondsToSelector:@selector(reverseString:)]);
}
我收到一条失败的消息说:
测试失败: - [ViewControllerTests testButtonActionAssigned]失败: (([self.vc.button respondsToSelector:@selector(reverseString :)])是 真的)失败
我的设置方法叫做:
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
self.vc = [[ViewController alloc] init];
NSLog(@"THIS METHOD IS CALLED");
}
是否与模拟器定时和启动有关?
答案 0 :(得分:1)
[self.button addTarget:self action:@selector(reverseString:) forControlEvents:UIControlEventTouchUpInside];
第一行表示reverseString:
方法应该在ViewController
中(由target:
参数指定,并在那里传递self
)。因此,只需删除.button
-(void)testButtonActionAssigned
{
XCTAssert([self.vc respondsToSelector:@selector(reverseString:)]);
}
以下是可以更改的小例子:
UIButton *button = [UIButton new];
[button addTarget:self action:@selector(doThat:) forControlEvents:UIControlEventTouchUpInside];
NSString *selectorString = [[button actionsForTarget:self forControlEvent:UIControlEventTouchUpInside] firstObject];
SEL sel = NSSelectorFromString(selectorString);
// so now you can check if target responds to selector
// BOOL responds = [self respondsToSelector:sel];
NSLog(@"%@", selectorString);
答案 1 :(得分:0)
我明白了。我正在测试错误的东西。
问题中的代码并未真正测试按钮是否已分配操作。它基本上是说“视图控制器是否响应此方法”或“视图控制器是否具有此方法”。
po UIApplication.sharedApplication().keyWindow!._firstResponder()
这意味着无论按钮是否指定了选择器,只要定义了该方法,该断言始终为真。
我通过评论代码行验证了它:
// this is saying "does the ViewController know about this method"
// rather than "is ViewController's button assigned method reverseString:"
XCTAssert([self.vc respondsToSelector:...]);
并且测试仍然通过,这不是我想要实现的目标。
正确的测试应为:
[self.button addTarget:self action:@selector(reverseString:) forControlEvents:UIControlEventTouchUpInside];
现在评论出来之后:
-(void)testButtonActionAssigned
{
[self.vc viewDidLoad];
NSArray *arrSelectors = [self.vc.button actionsForTarget:self.vc forControlEvent:UIControlEventTouchUpInside];
NSString *selector = nil;
if(arrSelectors.count > 0)
{
selector = arrSelectors[0];
}
XCTAssert([selector isEqualToString:@"reverseString:"]);
}
测试按预期失败:D
这个正确的测试代码从按钮中取出选择器并检查它是否确实是名为[self.button addTarget:self action:@selector(reverseString:) forControlEvents:UIControlEventTouchUpInside];
的方法
B.S.回答,并通过Apple的文档确认,更短的版本可以写成:
reverseString:
我原本担心在空数组上调用firstObject会导致应用程序崩溃,但Apple的文档向我确认firstObject是一个属性,如果数组为空则返回nil。
数组中的第一个对象。 (只读)
声明@property(非原子,只读)ObjectType firstObject
讨论如果数组为空,则返回nil。