es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

RxSwift/RxTest: Cómo probar una función asíncrona con retorno Observable

Soy bastante nuevo en RxSwift y estoy tratando de crear algunas pruebas unitarias. En este caso, quiero probar si la obtención de objetos desde la base de datos en tiempo real de Firebase está ocurriendo correctamente.

La función getAllPosts() devuelve un Observable de tipo [PostItem]:

func getAllPosts() -> Observable<[PostItem]> {
    ref = Database.database().reference()
    return Observable.create { observer -> Disposable in

        self.ref.child("Posts").observe(.value) { (snapshot) in
            var postsList: [PostItem] = []
            for child in snapshot.children {
                let snap = child as! DataSnapshot

                let postDict = snap.value as! [String: Any]
                let postAux = PostItem(id: snap.ref.key ?? "", authorId: postDict["authorId"] as? String ?? "", name: postDict["name"] as? String ?? "", content: postDict["content"] as? String ?? "", createAt: postDict["createAt"] as? String ?? "")
                postsList.append(postAux)
            }
            observer.onNext(postsList)
        }

        return Disposables.create {}
    }
}

El problema es que la respuesta de Firebase es asíncrona y la forma en que estoy intentando hacer la prueba se completa antes de la respuesta.

func testFetchPosts() throws {
    let newsAPIService = NewsAPIService()
    let posts = newsAPIService.fetchNewsFromAPI()

    XCTAssertNil(posts, "Las publicaciones son nil")
}

Obs: Intenté usar XCTest expectation pero no sé si lo implementé incorrectamente o si realmente no funciona.

¡Gracias!

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para probar correctamente la función getAllPosts(), debes usar RxTest y un planificador de pruebas para simular el comportamiento asíncrono de Firebase. Aquí tienes un ejemplo de implementación de prueba utilizando XCTest y RxTest:

    func testFetchPosts() {
        let scheduler = TestScheduler(initialClock: 0)
        let observer = scheduler.createObserver([PostItem].self)
    
        let sut = NewsAPIService()
    
        _ = sut.getAllPosts().subscribe(observer)
    
        let expectedPosts = [
            PostItem(id: "1", authorId: "user1", name: "Post 1", content: "Content 1", createdAt: "2021-01-01"),
            PostItem(id: "2", authorId: "user2", name: "Post 2", content: "Content 2", createdAt: "2021-01-02")
        ]
    
        // Simulamos que Firebase devuelve datos después de 1 segundo
        scheduler.scheduleAt(1) {
            sut.ref.child("Posts").setValue([
                "post1": [
                    "authorId": "user1",
                    "name": "Post 1",
                    "content": "Content 1",
                    "createdAt": "2021-01-01"
                ],
                "post2": [
                    "authorId": "user2",
                    "name": "Post 2",
                    "content": "Content 2",
                    "createdAt": "2021-01-02"
                ]
            ])
        }
    
        scheduler.start()
    
        // Comprobamos que el observador recibió los posts esperados
        XCTAssertEqual(observer.events.count, 1)
        XCTAssertEqual(observer.events[0].value.element, expectedPosts)
    }
    

    En esta prueba, creamos un TestScheduler y un TestObserver para la función getAllPosts(). También creamos una matriz de objetos PostItem esperados.

    Luego, nos suscribimos al Observable devuelto por getAllPosts() y programamos una actualización de los datos de Firebase después de 1 segundo.

    Finalmente, iniciamos el TestScheduler y comprobamos que el observador recibió los posts esperados.

    Ten en cuenta que esta prueba solo verifica que se recibieron los posts correctos. Para probar el manejo de errores y casos extremos, deberás crear pruebas adicionales.

Comments are closed.