1

Trying to unit test a network call and getting the following error:

API violation - multiple calls made to -[XCTestExpectation fulfill]

If written this style of testing before, but this one seems to be creating the error and I can't seem to figure out why.

func testAccessKeys() {
    let expected = expectation(description: "Run the Access request")
    sut.request(.Access, data: nil) { finished, response in
        if response != nil && finished == true {
            if let json = response as? [String:Any] {
                if json["id"] as? String != nil, json["secret"] as? String != nil {
                    XCTAssertNotNil(json)
                    expected.fulfill()
                } else {
                    XCTFail("Access response was not in correct format")
                    expected.fulfill()
                }
            } else {
                XCTFail("Access request was not a dictionary")
                expected.fulfill()
            }
        } else {
            XCTFail("Access response was nil")
            expected.fulfill()
        }
    }
    waitForExpectations(timeout: 3) { error in
        if let error = error {
            XCTFail("Access request failure: \(error.localizedDescription)")
        }
    }

}

UPDATE Simplifying the call solved the problem:

func testAccessKeys() {
    let expected = expectation(description: "Run the Access request")
    sut.request(.Access, data: nil) { finished, response in
        if response != nil && finished == true {
            if let json = response as? [String:Any] {
                if json["id"] as? String != nil, json["secret"] as? String != nil {
                    print("ID: \(String(describing: json["id"]))")
                    print("Secret: \(String(describing: json["secret"]))")
                    expected.fulfill()
                } else {
                    XCTFail("Access response was not in correct format")
                }
            } else {
                XCTFail("Access request was not a dictionary")
            }
        } else {
            XCTFail("Access response was nil")
        }
    }
    waitForExpectations(timeout: 3, handler: nil)
}
user7684436
  • 697
  • 14
  • 39
  • The answer for the first hit on Google lead me into [this](https://stackoverflow.com/questions/25167223/error-with-xctestexpectation-api-violation-multiple-calls-made-to-xctestexp), which seems to be a problem with asynchronous operations calling the `completionHandler` multiple times. Probably `sut.request` is doing something similar? – Alejandro Iván Apr 16 '18 at 13:12
  • sut.request is only being called once. Console confirms this. – user7684436 Apr 16 '18 at 13:14
  • Yes, but what does it do? You can call `sut.request` once, but that method could call a `completionHandler(finished, response)` more than once. Again, you better add some manual breakpoints on your code and try. – Alejandro Iván Apr 16 '18 at 13:16
  • `Sut.request` is a wrapper for a standard `Alamofire.request` call. – user7684436 Apr 16 '18 at 13:18
  • 1
    You should be calling `expected.fulfill()` as the last line of the completion handler. Maybe you should check if `finished == true` but if it only gets called once, as you say, then it would be unnecessary. – Guy Kogus Apr 16 '18 at 14:31

1 Answers1

0

I had the similar problem. I resolved it by making sure that the expectation.fulfill() is called only once. Also Make sure that your expectation has different description if you have more than one expectation. Eg:self.expectation(description: "expected description")
Calling it more than once leads to crash.
In my case I had a test case dependent on another test case. There the expectation was called more than once. I resolved it by making it as single one
You could have posted your UPDATE as answer!

BharathRao
  • 1,846
  • 1
  • 18
  • 28