unit test unit-testing mocking swift

unit-testing - unit testing swift 4



Burlarse de Swift (6)

@hpique Debido a las limitaciones que escribiste, OCMock no funciona muy bien en Swift (ya que todos los frameworks burlones dependen fuertemente del tiempo de ejecución)

Sin embargo, existen otras soluciones, desde semi manual (la simplificación de la escritura se burla de usted) hasta generadores simulados totalmente "automáticos", como:

https://github.com/MakeAWishFoundation/SwiftyMocky

Básicamente generará burlas para usted, con todos los prácticos métodos de verificación / verificación, etc., la configuración es bastante sencilla también.

Tiene sus limitaciones, pero admite una amplia gama de casos, incluidos los genéricos.

¿Cómo te burlas de un objeto en Swift?

El protocolo Mirror sonaba prometedor, pero no hace mucho en este momento.

Hasta ahora, el único enfoque que encontré es subclasificar y anular todos los métodos de la clase burlada. Esto, por supuesto, no es un verdadero simulacro, está lejos de ser ideal y requiere mucho trabajo.

¿Alguna otra idea?

¿Por qué no OCMock?

De la source :

¿Puedo usar OCMock usando la funcionalidad de puente de idioma?

Sí, pero con limitaciones. Si eres valiente Por ahora esto es altamente experimental. No hay garantía de que OCMock sea totalmente compatible con Swift.

Limitaciones conocidas

  • Las pruebas deben escribirse en Objective-C
  • Los objetos que se deben burlar deben heredar de NSObject
  • No se anulan / esperan / verifican los métodos de clase

Creo mis clases simuladas envolviendo todo en un protocolo. Yo mano roll una clase falsa para cumplir con el protocolo en cuestión, así:

protocol Dog: class { var name: String { get } func bark() } class DogImpl: Dog { var name: String init(name: String) { self.name = name } func bark() { print("Bark!") } } class DogMock: Dog { var name = "Mock Dog" var didBark = false func bark() { didBark = true } }

Utilizo esto junto con la inyección de dependencia para lograr una cobertura de prueba completa. Es un montón de repetitivo, pero hasta ahora no he tenido problemas con este enfoque.

Con respecto a la burla de las subclases, tendrá problemas con las clases final , o si tienen inicializadores no triviales.


Puedes lograr este tipo de burla con MockFive .

La esencia de esto es que tienes que crear un simulacro ''a mano'' de la clase fuente de la que quieres burlar--

pero luego, puede cortar sus métodos dinámicamente, para que pueda usarlo donde lo necesite y configurar su comportamiento allí.

Escribí un artículo sobre cómo usarlo here .


Quiero señalar algo además de la respuesta marcada: no sé si es un error o no.

Si subclasifica NSObject de alguna manera (en mi caso yo estaba subclasificando UIView que internamente subclase NSObject) necesita declarar explícitamente la función explicitada con @objc, de lo contrario su prueba no compilará. En mi caso, el compilador se bloquea con lo siguiente:

Falla de segmentación: 11

Entonces la siguiente clase:

public class ClassA: UIView { @objc public func johnAppleseed() { } }

Debería someterse a prueba unitaria de la siguiente manera:

class ClassATests: XCTestCase { func testExample() { class ClassAChildren: ClassA { @objc private override func johnAppleseed() { } } } }


Recomiendo usar Cuckoo , que puede manejar la mayoría de las tareas estándar de burla.

Clases de ejemplo:

class ExampleObject { var number: Int = 0 func evaluate(number: Int) -> Bool { return self.number == number } } class ExampleChecker { func check(object: ExampleObject) -> Bool { return object.evaluate(5) } }

Prueba de ejemplo:

@testable import App import Cuckoo import XCTest class ExampleCheckerTests: XCTestCase { func testCheck() { // 1. Arrange let object = MockExampleObject().spy(on: ExampleObject()) stub(object) { object in when(object.evaluate(any())).thenDoNothing() } let checker = ExampleChecker() // 2. Action checker.check(object) // 3. Assert _ = verify(object).number.get verify(object).evaluate(any()) verifyNoMoreInteractions(object) } }


NSHipster toca las funciones del lenguaje en Swift, lo que hace que una biblioteca de burla externa sea menos necesaria:

En Swift, las clases se pueden declarar dentro de la definición de una función, lo que permite que los objetos simulados sean extremadamente independientes. Simplemente declare una simulación de clase interna, anulación y [sic] métodos necesarios:

func testFetchRequestWithMockedManagedObjectContext() { class MockNSManagedObjectContext: NSManagedObjectContext { override func executeFetchRequest(request: NSFetchRequest!, error: AutoreleasingUnsafePointer<NSError?>) -> [AnyObject]! { return [["name": "Johnny Appleseed", "email": "[email protected]"]] } } ... }

La capacidad de crear una subclase de su dependencia externa en el ámbito local más la adición de XCTestExpectation resuelven muchos de los mismos problemas que OCMock .

Lo único que una biblioteca como OCMock ofrece es muy útil son sus métodos de "verificación" para garantizar que se invocaron las clases simuladas. Es posible agregar esto manualmente, pero la adición automática es agradable.