У меня есть следующий класс со статическим методом, который использует MKDirections для вычисления пользовательских маршрутов между двумя координатами. Как только он завершает вычисление, метод использует делегат для передачи маршрута (объект MKPolyline) в View Controller, который добавляет его в MapView в качестве наложения. Каждому маршруту присваивается заголовок, который определяет, каким цветом будет отображаться маршрут на карте.
class NavigationInterface {
weak static var routeDelegate: RouteDelegate!
static func addRouteFromTo(sourceCoor: CLLocationCoordinate2D, destinationCoor: CLLocationCoordinate2D, transportTypeString: String)
{
let sourcePlacemark = MKPlacemark(coordinate: sourceCoor)
let destinationPlacemark = MKPlacemark(coordinate: destinationCoor)
//var route = MKRoute()
let request = MKDirectionsRequest()
request.source = MKMapItem(placemark: sourcePlacemark)
request.destination = MKMapItem(placemark: destinationPlacemark)
request.requestsAlternateRoutes = false
//get MKDirectionsTransportType based on String identifier
request.transportType = getTransportType(transportTypeString: transportTypeString)
let directions = MKDirections(request: request)
directions.calculate { (response, error) in
if let directionResponse = response?.routes.first {
let route = directionResponse.polyline
route.title = transportTypeString
print("Got Here")
self.routeDelegate!.didAddRoute(route: route)
}
}
}
Делегат определяется через следующий протокол:
protocol RouteDelegate: class {
func didAddRoute(route: MKPolyline)
func didAddBoundary(boundary: MKPolygon)
}
View Controller реализует делегат следующим образом:
class MapViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
...
override func viewDidLoad() {
super.viewDidLoad()
NavigationInterface.routeDelegate = self
}
extension MapViewController: RouteDelegate {
// delegate Method
// called in Navigation Interface
func didAddRoute(route: MKPolyline) {
mapView.add(route)
}
func didAddBoundary(boundary: MKPolygon) {
mapView.add(boundary)
}
}
Теперь я попытался написать UnitTest, который проверяет, возвращает ли метод делегата "didAddRoute" правильный маршрут
Для этой цели я создал тестовый класс "NavigationTests", который реализует протокол RouteDelegate и метод теста, который вычисляет маршрут, а затем оценивает маршрут, возвращенный из реализации протокола "NavigationTests" объекта "didAddRoute":
class NavigationTests: XCTestCase, RouteDelegate {
var routes = [MKPolyline]()
var asyncExpectation: XCTestExpectation?
func didAddRoute(route: MKPolyline) {
routes.append(route)
asyncExpectation?.fulfill()
}
...
func testaddRouteFromTo(){
NavigationInterface.routeDelegate = self
asyncExpectation = expectation(description: "routes returned from delegate method")
NavigationInterface.addRouteFromTo(sourceCoor: CoordinateA, destinationCoor: CoordinateB, transportTypeString: "roadTravel")
let result = XCTWaiter.wait(for: [self.asyncExpectation!], timeout: 2.0)
if result == XCTWaiter.Result.completed {
let route = self.routes.first
XCTAssert(route!.title == "roadTravel", "failed to retrieve correct route")
print(route!.title)
} else {
XCTFail()
}
}
}
Теперь этот метод тестирования случайным образом возвращает маршруты из реализации MapViewController в RouteDelegate вместо реализации NavigationTests. W
Как я могу избежать этих нежелательных ссылок на MapViewController и почему он вообще создается, поскольку я не создаю его в тесте?
В идеале я хотел бы предотвратить создание экземпляра MapViewController при запуске этого тестового класса, поскольку он не требуется для модульного теста.
Как я могу убедиться, что используется только реализация NavigationTests RouteDelegate?