RxSwiftCommunity / RxNimble

Nimble extensions making unit testing with RxSwift easier :tada:

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't use beAnInstanceOf to match Expectations

SunDog opened this issue · comments

When comparing instances or classes the methods beAnInstanceOf and beAKindOf returns a Predicate<Any> but RxNimble expectation ask's for Predicate<T> instead.

Code:

let driverObject = Driver.just(Int())

// doesn't compile
expect(driverObject.asObservable()).first.to(beAnInstanceOf(Int.self))

// compile
let result = try! driverObject.asObservable().toBlocking().first()
expect(result).to(beAnInstanceOf(Int.self))

I don't know if it is as expected or if we can improve this.
Therefore I'm at your disposal to make a PR for this, but I would need some direction since I think this is not as easy as just changing the type of var first

Hmm! Sounds like you may have found a bug. We recently refactored the internals to support RxTest in #35, maybe this is a limitation we've hit? I'm not sure. The docs for Nimble's custom matchers are here: https://github.com/Quick/Nimble#writing-your-own-matchers Not sure about RxTest but I'd start in our Nimble implementation: https://github.com/RxSwiftCommunity/RxNimble/blob/master/Source/RxTest/Expectation%2BRxTest.swift A PR would be very welcome, thanks 🙇

Hey @SunDog thank you for reporting this.
I don't think, it's an issue with RxNimble. It's just the way it was implemented

expect(subject).first 

resolves as Expectation<Int>, so we can't check its type. Because we know it for sure.
RxTest has another API, which extends ObservableConvertibleType type. So it doesn't change behaviour of expect method.
if you want to get such behaviour, you can use:

let driverObject: Driver<Any> = Driver.just(Int())
// will compile
expect(driverObject.asObservable()).first.to(beAnInstanceOf(Int.self))

The only way to resolve this issue - fully rethink API of RxNimble. first shouldn't be in extension of Expectation, but in ObservableConvertibleType. Like this:

public extension ObservableConvertibleType {
    var first: Element {
        return try! self.toBlocking().first()! // dirty version with force unwrap
    }
}
...
expect(o.first).to(beAnInstanceOf(Int.self)) // compiles

If maintainers are ok with that, i will create PR @gobetti

Hi @ashfurrow @MortyMerr !
You guys mentioned RxTest, so just making sure we're on the same page: I think grabbing the first only makes sense when using RxBlocking, because the idea with RxTest is to test a sequence instead of specific events (we would need to block it until the first one is received if we want one event, right?). So @MortyMerr your proposed solution makes sense to me, as long as it's part of the RxBlocking subspec only.
Please feel free to correct me if I'm wrong! 🙏

@gobetti these declarations will conflict with first() from Observable
I think it's better to just ignore beAnInstanceOf or use the approach with explicit type