Home > database >  Swift 5.5 Await Async Mocking and Unit Tests - Alamofire
Swift 5.5 Await Async Mocking and Unit Tests - Alamofire

Time:02-16

Lets say I have something like this

import Alamofire

class NetworkStuff {
    
    func getSomething() async throws -> String {
        let params: [String: String] = ["Key": "Value"]
    
        let value = AF.request("https://myapi.com/endpoint", method: .post, parameters:  params, encoder: JSONParameterEncoder.default)
            .validate()
            .responseDecodable([String: String].self).value("KeyIWant")
        guard let result = value else {throw MyError.SomeError }
        return result
    }
}

How would I go about writing a unit test to validate that this request is right and that im decoding the response. Lets say we send this to the server:

{
"RequestItem": "Value"
}

Lets say the response from the server looks like:

{
  "ID": "1234",
  "KeyIWant": "Value02"
}

How could I write a test to ensure my POST parameters were structured correctly as the server expects and then mock a response so that I ensure im parsing this correctly to get the value I want?

CodePudding user response:

Keep in mind that you do not want to test the network or AlamoFire or the server at the endpoint. You want to test only your code.

To do that, you need to make your code testable. Break out getSomething into subroutines that are testable — this sort of thing:

func getSomething() async throws -> String {
    let params = self.constructParams()
    let value = AF.request("https://myapi.com/endpoint", method: .post, parameters:  params, encoder: JSONParameterEncoder.default)
    let result = self.processValue(value)
    return result
}

Now constructParams and processValue are methods that you can test by normal means, providing various inputs and checking to see that you get back the expected outputs.

CodePudding user response:

I will break the answer into two parts (I assume you are familiar with XCTest framework or its open-source wrappers, Quick and Nimble, those are my recommendation to be used for testing):

First, writing a test to make sure the POST parameters are structured correctly - I would reconstruct the function and pass them as an argument to it. Then I would write a class that is in charge of building the parameters and write a testing suite for it - making sure it builds the parameters correctly, something like

final class ParamBuilder {
  func params() -> [String: Any] { ["Key": "Value"] }
}

// Testing
class ParamBuildierTests: XCTestCase {

  func testFirst() {
      let builder = ParamBuilder()
       XCTAssertEqual(builder.params(), ["Key": "Value"])
  }
}

Second, mock and test response. I personally recommend using Mockingjay Its usage is pretty straightforward, and it can mock response such that you can keep using the same service NetworkStuff which is using Alamofire (URLSession underlying). It will stub the response according to your preference - you can mock 404 response and different payloads

  • Related