GitHawkApp / GitHawk

The (second) best iOS app for GitHub.
http://githawk.com
MIT License
2.88k stars 384 forks source link

Network stack mock #697

Open Iron-Ham opened 6 years ago

Iron-Ham commented 6 years ago

Ref #568

way i see it, we won't be able to creep up that VC test cov until we have a mock for the client and all of the little guys it needs along the way. good mock should be able to to take a local path to a response and return that to the tests.

BasThomas commented 5 years ago

Think we have this now?

rnystrom commented 5 years ago

I never landed it 😞 I’ve been thinking about refactoring all the client stuff to be a protocol so a unit test or UI test can swap in its own stub

Sent with GitHawk

BrianLitwin commented 5 years ago

@rnystrom @BasThomas or any Upperclassmen:

I've tried subclassing the Client, I've tried moving the request methods into a protocol:

ClientRequestPerformer ```swift public protocol ClientRequestPerformer { func send(_ request: T, completion: @escaping (Result) -> Void) func query( _ query: T, result: @escaping (T.Data) -> Q?, completion: @escaping (Result) -> Void ) -> Cancellable func mutate( _ mutation: T, result: @escaping (T.Data) -> Q?, completion: @escaping (Result) -> Void ) -> Cancellable } ```


But I'm not able to test anything using either strategy. I feel like I'm missing something basic (to do with GitHubAPI being in a separate pod?), b/c I can't even set and trip a breakpoint or print anything to the console in the Client's query methods, either in a test or running the app in the simulator.

I don't think it's a threading issue (I've tried using asynchronous promise/expectations) and I've imported the GitHubAPI: @testable import GitHubAPI.

Would love to figure out how to do this so that we can write more tests.

rnystrom commented 5 years ago

@BrianLitwin are you using Xcode 10? The new build system has a bug that won’t rebuild pods. Clean and build or change to the old build system and it’ll work. Hopefully that’s what you were hitting?

Sent with GitHawk

BasThomas commented 5 years ago

Does it? Cocoapods works for us at work (it didn't use to until the last beta)

BrianLitwin commented 5 years ago

Good news! Getting the latest XCode beta worked! Good tip @BasThomas !

so the following code works for me to subclass the Client:

extension GithubClient {
    init(mockClient: Client) {
        self.userSession = nil
        self.cache = FlatCache()
        self.bookmarksStore = nil
        self.client = mockClient
        self.badge = BadgeNotifications(client: mockClient)
    }
}

class MockClient: Client {
    init() {
        let config = ConfiguredNetworkers(
            token: nil,
            useOauth: nil
        )
        super.init(
            httpPerformer: config.alamofire,
            apollo: config.apollo,
            token: nil
        )
    }

    override func send<T>(_ request: T, completion: @escaping (Result<T.ResponseType>) -> Void) where T : HTTPRequest {
        print("Seen")
    }

}

I'm pretty stoked about that.

Bad new is that trying to use a protocol-based mock strategy is giving me trouble. If one of y'all want to try to repro this, it shouldn't be too hard:

in the GitHubAPI pod paste:

public protocol SampleDelegate {
public func send<T: HTTPRequest>(_ request: T, completion: @escaping (Result<T.ResponseType>) -> Void)
}

and then try to get anything in the test suite to conform to that protocol w/o the compiler complaining. It gives me a never ending: class does not conform error, suggests I add the same function I've already got in there, etc.

As an aside, I have no problems conforming to the following:

// compiler in the test suite doesn't complain about conforming to this: 
public protocol SampleDelegate {
public func send<T: HTTPRequest>(_ request: T) -> Void)
}

Anyway, I feel optimistic that subclassing Client could go a long ways.