title: Unit Testing URL Parameters in Swift
body: <p>I am trying to unit a <code>URL</code> in Swift by using TDD. I want to ensure that the <code>URL</code> is equal to the expected <code>URL</code>. I am using a <code>Router</code> <code>enum</code>, using <code>Alamofire</code>, to create my <code>URL</code>s. So, as property of the <code>Router</code> <code>enum</code>, I have a <code>Dictionary&lt;String,String&gt;?</code> property because I may not need parameters for other <code>URL</code>s. However, I do need parameters for the authentication <code>URL</code>.</p>
  
  <p>The <code>parameters</code> <code>Dictionary&lt;String,String&gt;?</code> follows:</p>
  
  <pre class="lang-swift prettyprint-override"><code>internal enum Router: URLConvertible {
  
      internal static let baseURLString = "https://xxx.xxxxxx.xxx"
  
      case authentication(clientID: String)
  
  }
  
  extension Router {
  
      var pathString: String {
          switch self {
              case .authentication: return "xxxxx/xxxxx/xxxxxxxxx"
          }
      }
  
      var method: HTTPMethod {
          switch self {
              case .authentication: return .get
          }
      }
  
      var parameters: Dictionary&lt;String, String&gt;? {
          switch self {
              case .authentication(let clientID): return ["xxxxx": "xxxx", "client_id": clientID]
          }
      }
  
      func asURL() throws -&gt; URL {
          switch self {
              case .authentication:
                 return URL(string: "https://xxx.xxxxxx.xxx/xxxxx/xxxxx/xxxxxxxxx?xxxxx=xxxx&amp;client_id=xxxxxxxxxx")!
          }
      }
  
  }
  </code></pre>
  
  <p>I have been able to successfully code everything the TDD way up to this point. Where I am stuck is testing the returned <code>URL</code>. Since <code>parameters</code> is of type <code>Dictionary&lt;String,String&gt;?</code>, I want to iterate <code>parameters</code> by using the following logic:</p>
  
  <pre class="lang-swift prettyprint-override"><code>var parametersStringArray = Array&lt;Dictionary&lt;String,String&gt;&gt;()
  
  for (key, value) in parameters {
      // Create a parameter string from each set
      // Something like the following:
      let parameterString = String(describing: \(key)=\(value))
      parametersStringArray.append(parameterString)
  }
  
  let parametersString = parametersStringArray.joined(separator: "&amp;")
  let fullURLString = baseURLString + "?\(parametersString)"
  return URL(string: fullURLString)!
  </code></pre>
  
  <p>By creating the parameters like this, when I test the expected <code>URL</code> against the returned <code>URL</code> from the <code>Router</code> <code>enum</code> in <code>asURL() throws -&gt; URL</code>, it could fail part of the time since the parameters are added to the <code>URL</code> string without an expected order. In other words, If my expected URL is <code>https://xxx.xxxxxx.xxx?xxxxx=xxxx&amp;client_id=xxxxxxxxxx</code>, it could either match or fail by returning the parameters in the reverse order, like so: <code>https://xxx.xxxxxx.xxx?client_id=xxxxxxxxxx&amp;xxxxx=xxxx</code>.</p>
  
  <p>Is there a better solution for me testing the <code>URL</code>s to ensure that the correct <code>URL</code> is returned when the parameters can be in any order since they are added to the <code>URL</code>'s string when iterating them?</p>
  
  <p>Should I create two <code>URL</code>s with the parameters both ways and match against either? The reason that I don't see that being appropriate is because the more parameters you have, the more <code>URL</code>s you have to create to test against.</p>
  
  <p>My current tests for testing the <code>URL</code> for authentication follow:</p>
  
  <pre class="lang-swift prettyprint-override"><code>import XCTest
  import Alamofire
  @testable import Projects
  
  class AuthenticationURLTests: XCTestCase {
  
      func test_API_BaseURLString_IsCorrect() {
          let baseURLString = Router.baseURLString
          let expectedBaseURLString = "https://xxx.xxxxxx.xxx/"
          XCTAssertEqual(baseURLString, expectedBaseURLString, "Base URL does not match expected base URL. Expected base URLs to match.")
      }
  
      func test_API_OAuthPath_IsCorrect() {
          let pathString = Router.authentication(clientID: "xxxxxxxxxx").pathString
          let expectedPathString = "xxxxx/xxxxx/xxxxxxxxx"
          XCTAssertEqual(pathString, expectedPathString, "Path string does not match expected path string. Expected path strings to match.")
      }
  
      func test_API_OAuthMethod_IsCorrect() {
          let method = Router.authentication(clientID: "xxxxxxxxxx").method
          let expectedMethod = HTTPMethod.get
          XCTAssertEqual(method, expectedMethod, "HTTP methods do not match. Expected HTTP methods to match.")
      }
  
      func test_API_OAuth_ParametersContainsKeyForXXXXX() {
          let scopeString = Router.authentication(clientID: "xxxxxxxxxx").parameters?["xxxxx"]
          let expectedScopeString = "xxxx"
          XCTAssertEqual(scopeString, expectedScopeString, "Scope strings do not match. Expected scope strings to match.")
      }
  
      func test_API_OAuth_ParametersContainsKeyForClientID() {
          let clientID = Router.authentication(clientID: "12345abcde").parameters?["client_id"]
          let expectedClientID_Fake = "12345abcde"
          XCTAssertEqual(clientID, expectedClientID_Fake, "Client IDs do not match. Expected client IDs to match.")
      }
  
      func test_API_OAuth_URLIsCorrect() {
          do {
              let url = try Router.authentication(clientID: "12345abcde").asURL()
              // Here, I want to ensure that the `URL`s match:
              let expectedURL = URL(string: https://xxx.xxxxxx.xxx?xxxxx=xxxx&amp;client_id=xxxxxxxxxx)!
          } catch { XCTFail("Could not create URL for OAuth") }
      }
  
  }
  </code></pre>
  
  <p>Sorry for all of the <code>x</code>s within the provided code. I wanted to ensure that I didn't provide any information regarding my client's application.</p>