Files
Dip/Tests/DipTests/RuntimeArgumentsTests.swift
2020-04-23 09:59:03 +02:00

283 lines
8.9 KiB
Swift

//
// Dip
//
// Copyright (c) 2015 Olivier Halligon <olivier@halligon.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
@testable import Dip
private protocol Service {
var name: String { get }
}
private class ServiceImp: Service {
let name: String
init(name: String, baseURL: String, port: Int) {
self.name = name
}
}
private class ServiceImp1: Service {
let name: String = "ServiceImp1"
}
private class ServiceImp2: Service {
let name: String = "ServiceImp2"
}
class RuntimeArgumentsTests: XCTestCase {
let container = DependencyContainer()
override func setUp() {
container.reset()
}
func testThatItResolvesInstanceWithOneArgument() {
//given
let arg1 = 1
container.register(factory: { (a1: Int) -> Service in
XCTAssertEqual(a1, arg1)
return ServiceImp1()
})
//when
let service = try! container.resolve(arguments: arg1) as Service
//then
XCTAssertTrue(service is ServiceImp1)
//when
let anyService = try! container.resolve(Service.self, arguments: arg1)
//then
XCTAssertTrue(anyService is ServiceImp1)
}
func testThatItResolvesInstanceWithTwoArguments() {
//given
let arg1 = 1, arg2 = 2
container.register { (a1: Int, a2: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
return ServiceImp1()
}
//when
let service = try! container.resolve(arguments: arg1, arg2) as Service
//then
XCTAssertTrue(service is ServiceImp1)
//when
let anyService = try! container.resolve(Service.self, arguments: arg1, arg2)
//then
XCTAssertTrue(anyService is ServiceImp1)
}
func testThatItResolvesInstanceWithThreeArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3
container.register { (a1: Int, a2: Int, a3: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
return ServiceImp1()
}
//when
let service = try! container.resolve(arguments: arg1, arg2, arg3) as Service
//then
XCTAssertTrue(service is ServiceImp1)
//when
let anyService = try! container.resolve(Service.self, arguments: arg1, arg2, arg3)
//then
XCTAssertTrue(anyService is ServiceImp1)
}
func testThatItResolvesInstanceWithFourArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3, arg4 = 4
container.register { (a1: Int, a2: Int, a3: Int, a4: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
XCTAssertEqual(a4, arg4)
return ServiceImp1()
}
//when
let service = try! container.resolve(arguments: arg1, arg2, arg3, arg4) as Service
//then
XCTAssertTrue(service is ServiceImp1)
//when
let anyService = try! container.resolve(Service.self, arguments: arg1, arg2, arg3, arg4)
//then
XCTAssertTrue(anyService is ServiceImp1)
}
func testThatItResolvesInstanceWithFiveArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3, arg4 = 4, arg5 = 5
container.register { (a1: Int, a2: Int, a3: Int, a4: Int, a5: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
XCTAssertEqual(a4, arg4)
XCTAssertEqual(a5, arg5)
return ServiceImp1()
}
//when
let service = try! container.resolve(arguments: arg1, arg2, arg3, arg4, arg5) as Service
//then
XCTAssertTrue(service is ServiceImp1)
//when
let anyService = try! container.resolve(Service.self, arguments: arg1, arg2, arg3, arg4, arg5)
//then
XCTAssertTrue(anyService is ServiceImp1)
}
func testThatItResolvesInstanceWithSixArguments() {
let arg1 = 1, arg2 = 2, arg3 = 3, arg4 = 4, arg5 = 5, arg6 = 6
container.register { (a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int) -> Service in
XCTAssertEqual(a1, arg1)
XCTAssertEqual(a2, arg2)
XCTAssertEqual(a3, arg3)
XCTAssertEqual(a4, arg4)
XCTAssertEqual(a5, arg5)
XCTAssertEqual(a6, arg6)
return ServiceImp1()
}
//when
let service = try! container.resolve(arguments: arg1, arg2, arg3, arg4, arg5, arg6) as Service
//then
XCTAssertTrue(service is ServiceImp1)
//when
let anyService = try! container.resolve(Service.self, arguments: arg1, arg2, arg3, arg4, arg5, arg6)
//then
XCTAssertTrue(anyService is ServiceImp1)
}
func testThatItRegistersDifferentFactoriesForDifferentNumberOfArguments() {
//given
let arg1 = 1, arg2 = 2
container.register { (a1: Int) in ServiceImp1() as Service }
container.register { (a1: Int, a2: Int) in ServiceImp2() as Service }
//when
let service1 = try! container.resolve(arguments: arg1) as Service
let service2 = try! container.resolve(arguments: arg1, arg2) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatItRegistersDifferentFactoriesForDifferentTypesOfArguments() {
//given
let arg1 = 1, arg2 = "string"
container.register(factory: { (a1: Int) in ServiceImp1() as Service })
container.register(factory: { (a1: String) in ServiceImp2() as Service })
//when
let service1 = try! container.resolve(arguments: arg1) as Service
let service2 = try! container.resolve(arguments: arg2) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatItRegistersDifferentFactoriesForDifferentOrderOfArguments() {
//given
let arg1 = 1, arg2 = "string"
container.register { (a1: Int, a2: String) in ServiceImp1() as Service }
container.register { (a1: String, a2: Int) in ServiceImp2() as Service }
//when
let service1 = try! container.resolve(arguments: arg1, arg2) as Service
let service2 = try! container.resolve(arguments: arg2, arg1) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatNewRegistrationWithSameArgumentsOverridesPreviousRegistration() {
//given
let arg1 = 1, arg2 = 2
container.register { (a1: Int, a2: Int) in ServiceImp1() as Service }
let service1 = try! container.resolve(arguments: arg1, arg2) as Service
//when
container.register { (a1: Int, a2: Int) in ServiceImp2() as Service }
let service2 = try! container.resolve(arguments: arg1, arg2) as Service
//then
XCTAssertTrue(service1 is ServiceImp1)
XCTAssertTrue(service2 is ServiceImp2)
}
func testThatDifferentFactoriesRegisteredIfArgumentIsOptional() {
//given
let name1 = "1", name2 = "2"
container.register { (port: Int, url: String) in ServiceImp(name: name1, baseURL: url, port: port) as Service }
container.register { (port: Int, url: String?) in ServiceImp(name: name2, baseURL: url!, port: port) as Service }
//when
let service1 = try! container.resolve(arguments: 80, "http://example.com") as Service
let service2 = try! container.resolve(arguments: 80, "http://example.com" as String?) as Service
//then
XCTAssertEqual(service1.name, name1)
XCTAssertEqual(service2.name, name2)
//Due to incomplete implementation of SE-0054 (bug: https://bugs.swift.org/browse/SR-2143)
//registering definition with T? and T! arguments types will produce two different definitions
//but when argument of T! will be passed to `resolve` method it will be transformed to T?
//and wrong definition will be used
//When fixed using T? and T! should not register two different definitions
// let name3 = "3"
// container.register { (port: Int, url: String!) in ServiceImp(name: name3, baseURL: url, port: port) as Service }
// let service3 = try! container.resolve(arguments: 80, "http://example.com" as String!) as Service
// XCTAssertEqual(service3.name, name3)
}
}