对于iOS tdd测试/模拟你会推荐哪个框架?我听说OcMock已经存在更长时间并且更轻巧.任何人都可以提供一些优点和缺点的例子或演示每个的优点.我只是在寻找一个快速的标准模拟框架,但我想知道每个框架的所有缺点/好处.
我想单元测试充当一个类CBPeripheralManagerDelegate 的CBPeripheralManager类。通常,为了排除外部类依赖项,我会使用一种形式的依赖项注入,通过类初始值设定项或通过属性传入。在处理基于单例的 API 时,我已经能够使用像 Kiwi 这样的库来存根返回单例的类级方法(即[ClassName stub:@selector(sharedInstance) andReturn:myStubbedInstance])。模拟情况下的问题CBPeripheralManager是它的初始值设定项采用委托实例。所以任何使用我的类的代码都需要做这样的事情:
PeripheralManagerWrapper *wrapper = [[PeripheralManagerWrapper alloc] init];
CBPeripheralManager *peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:wrapper queue:nil options:nil];
wrapper.peripheralManager = peripheralManager;
Run Code Online (Sandbox Code Playgroud)
然后,为了对我的PeripheralManagerWrapper类进行单元测试,我可以简单地实例化它并传入一个模拟的CBPeripheralManager. 但是,我不喜欢要求我的包装器对象的任何调用代码都必须经过此设置。有没有更好的模式来处理这种情况?我已经使用了 Kiwi 和 OCMockito,但似乎都没有提供这个功能,除非可能存根alloc和init方法,CBPeripheralManager然后只是在PeripheralManagerWrapper
的初始化程序中实例化实例。
我正在使用OCMockito,我想在我的ViewController中测试一个使用NetworkFetcher对象和块的方法:
- (void)reloadTableViewContents
{
[self.networkFetcher fetchInfo:^(NSArray *result, BOOL success) {
if (success) {
self.model = result;
[self.tableView reloadData];
}
}];
}
Run Code Online (Sandbox Code Playgroud)
特别是,我想要模拟,fetchInfo:以便它返回一个虚拟result数组而不会访问网络,并验证该reloadData方法是否被调用,UITableView并且模型应该是它应该是什么.
由于此代码是异步的,我假设我应该以某种方式捕获块并从我的测试中手动调用它.
我怎么能做到这一点?
继TDD之后,我正在开发一款iPad应用程序,可以从互联网上下载一些信息并将其显示在列表中,允许用户使用搜索栏过滤该列表.
我想测试一下,当用户在搜索栏中输入内容时,会更新带有过滤器文本的内部变量,更新过滤的项目列表,最后表格视图会收到"reloadData"消息.
这些是我的测试:
- (void)testSutChangesFilterTextWhenSearchBarTextChanges
{
// given
sut.filterText = @"previous text";
// when
[sut searchBar:nil textDidChange:@"new text"];
// then
assertThat(sut.filterText, is(equalTo(@"new text")));
}
- (void)testSutReloadsTableViewDataAfterChangeFilterTextFromSearchBar
{
// given
sut.tableView = mock([UITableView class]);
// when
[sut searchBar:nil textDidChange:@"new text"];
// then
[verify(sut.tableView) reloadData];
}
Run Code Online (Sandbox Code Playgroud)
注意:更改"filterText"属性现在会触发实际的过滤过程,该过程已在其他测试中进行了测试.
这工作正常,因为我的searchBar委托代码编写如下:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
self.filterText = searchText;
[self.tableView reloadData];
}
Run Code Online (Sandbox Code Playgroud)
问题是过滤这些数据正变成一个繁重的过程,现在正在主线程上完成,因此在此期间UI被阻止.
因此,我想做这样的事情:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSArray *filteredData = [self filteredDataWithText:searchText];
dispatch_async(dispatch_get_main_queue(), ^{
self.filteredData = filteredData; …Run Code Online (Sandbox Code Playgroud) unit-testing objective-c objective-c-blocks dispatch-async ocmockito
假设我正在为tableView:cellForRowAtIndexPath:视图控制器上的委托方法编写单元测试。根据我传入的索引路径,此方法可以返回几个不同的单元配置。
我可以轻松地断言该cell.textLabel.text属性。但是,如何断言该cell.imageView.image属性包含正确的图像?图像或imageView都不具有(公共API)属性,我可以使用这些属性来查找图像名称或文件名。
我想出的最好办法是创建最小的有效.png(使用它,[UIImage imageWithData:]以便在单元测试中不要碰到磁盘),并断言从中获得的字节数组cell.imageView.image是我期望的字节数组。我创建了一个OCHamcrest匹配器,以使其变得更好一点,但这是一种不令人满意且不灵活的方法。
有谁有更好的主意?
我可以存根/验证类方法,但是我对定义的宏有困难.我正在尝试测试我的一个方法调用DDLogInfo.
它在CocoaLumberjack源代码中定义如此
#define DDLogInfo(frmt, ...) LOG_MAYBE(LOG_ASYNC_ENABLED, LOG_LEVEL_DEF, DDLogFlagInfo, 0, nil, __PRETTY_FUNCTION__, frmt, ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在尝试验证模拟对象上的函数是否完全没有使用任何参数调用.
我正在嘲笑的对象上的函数是......
- (void)registerUserWithUsername:(NSString*)username password:(NSString*)password;
Run Code Online (Sandbox Code Playgroud)
如果用户名为空,我想验证是否未调用该函数.
即
[mockService registerUserWithUsername:@"" password:@"Password"];
[verify(mockService, never()) registerWithUsername:....... password:.......];
Run Code Online (Sandbox Code Playgroud)
我只是不确定要把......放在什么位?
如何使用OCMockito捕获具有原始值的参数?
MKTArgumentCaptor似乎只能捕获对象类型?Xcode说"与整数转换不兼容".
我想使用以下消息声明来模拟对象:
- (void)createWithCompletion:(void (^)(FuseResult *result, NSError *err)) completion;
是否可以模拟此消息必须处理的块调用?
我读过有块的ArgumentCaptorTest,但我不确定它是否相关.
用于方法签名
- (void)insertValue:(NSUInteger)value;
Run Code Online (Sandbox Code Playgroud)
我试图看看insertValue是否永远不会被调用.
[verifyCount(test, never()) insertValue:0];
Run Code Online (Sandbox Code Playgroud)
由于编译器抱怨任何()原始类型,我该如何测试呢?
我想测试我的init*方法是否使用OCMockito调用其体内的其他方法.这是可能的,如果,我该怎么办?比方说,我想检查是否[self myMethod]已被调用.
我一直试图以这种天真的方式做到这一点,但你可以想象,没有成功:
it(@"should trigger myMethod", ^{
DetailsView *mockDetailsView = mock([DetailsView class]);
[mockDetailsView initWithFrame:CGRectZero];
[verify(mockDetailsView) myMethod];
});
Run Code Online (Sandbox Code Playgroud) 我在ClassA中有这两种方法
-(IBAction)onSubmit;
-(void)validateName:(NSString*)name;
Run Code Online (Sandbox Code Playgroud)
@implementation
- (IBAction)onSubmit {
[self validateName:self.textfield.text];
}
-(void)validateName:(NSString*)name{
// do something
}
Run Code Online (Sandbox Code Playgroud)
我的测试如下所示:
//given
ClassA *classA = mock([ClassA class]);
classA.textfield.text = @"Foo";
// when
[classA onSubmit];
[verify(classA) validateName:@"Foo"];
Run Code Online (Sandbox Code Playgroud)
但这不起作用,我一直在:
Expected 1 matching invocation, but received 0
Run Code Online (Sandbox Code Playgroud)
在调用onSubmit时,如何编写验证validateName是否已执行的测试.
我有一个简单的(我猜)问题.
我想在我的应用程序中使用Specta和KIF进行功能测试.问题是我在我的View Controller的viewDidLoad方法中设置依赖,并且在我的规范的beforeEach方法中我注入假对象只是为了不打网络.
结果是错误的,因为在规范中的beforeEach方法之前调用了viewDidLoad.
是否有可能在AppDelegate加载根视图控制器之前设置依赖关系,以便正确设置所有内容?
ocmockito ×13
ios ×8
objective-c ×7
unit-testing ×7
ochamcrest ×2
tdd ×2
kif ×1
kiwi ×1
mocking ×1
ocmock ×1
specta ×1
testing ×1
xcode ×1