Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Custom matcher behaves differently than built in matcher under async #125

Open
iosdev-republicofapps opened this issue Jan 9, 2015 · 0 comments

Comments

@iosdev-republicofapps
Copy link
Contributor

Hi,

First, I love Expecta, thanks so much for your hard work!

Here's what I'm trying to do:

@interface Person : NSObject
@property (nonatomic, copy) NSString *surname;
@end

// Person.surname starts out as nil.  I want to test an async process that eventually
// (after say 0.1s) sets Person.surname to some non-nil value.
Person *person = [[Person alloc] init];

// I tried this but it barfed with:
//  nil/null is not an instance of NSString or NSFastEnumeration
expect(person.name).will.contain(@"foo");

// I know nil is not an instance of NSString or NSFastEnumeration.  That's because
// person.name is nil when the expect method is invoked.  But person.name will
// become non-nil after the async process finishes.

// OK, so I went in to EXPMatchers+contain.m in the Expecta source and changed
BOOL actualIsCompatible = [actual isKindOfClass:[NSString class]] || [actual conformsToProtocol:@protocol(NSFastEnumeration)];

// ... to
BOOL actualIsCompatible = YES;

// Now if I run, the test passes as desired.
// I know this change was potentially unsafe if actual is non-nil and not an NSString
// or NSFastEnumeration, but I'm just hacking to make things work for my one test
// case first before finding a better solution ...

// OK, so now I copy EXPMatchers+contain.[h, m] verbatim and make my own version called
// EXPMatchers+containEventually.[h, m] (and I replace "contain" with "containEventually"
// everywhere in these two files.
// I drop these in my own source tree, not the Expecta tree, and include them in my test file.

// Now, you would think that
expect(person.name).will.containEventually(@"foo");

// ... would behave identically to my modified contain from the Expecta source because
// it's exactly the same code, except that "contain" has been replaced by "containEventually"
// ...

// ... but it doesn't.  Somehow the same exact (line-for-line) code that works when
// compiled inside the Expecta source behaves differently when included directly
// in my project ...

Any ideas?

What I need to test is the following:

  • That a value that is currently nil will eventually, when it gets set to non-nil, contain some value "foo"
  • When expect(value) is invoked, value is nil, but it will become non-nil later due to an async process

How can I test this?

Thanks!

NOTE: If I put an NSLog statement in the match invocation in the modified contain and containEventually .m files, I can see that match gets called repeatedly. The values passed are actual == nil many times. Eventually, the regular contain gets an actual != nil. The containEventually never does ... I don't understand why. Hope that helps.

NOTE 2: This doesn't happen with expect(person.name).will.equal(@"foo") (in that case the transition from nil to foo is handled as expected) - it only happens with contain, not equal. Does that help?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant