Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Testing de componentes React: ¿cuándo y por qué necesitamos usar act()?

Posted on Oct 21 ¿A quién no le ha pasado? Cuando hacemos test de componentes React, de vez en cuando nos encontramos con este warning:Aunque el mensaje es bastante claro (una vez que lo entendemos), es habitual no entender ni por qué aparece, ni cómo solucionarlo, dando como resultado que acabemos ignorándolo. Cuando hacemos una actualización de estado en un componente, React se encarga de volver a renderizarlo para actualizar el DOM si es necesario. Esto ocurre automáticamente como respuesta a los eventos de usuario (clicks, input, etc.) gestionados por React. Ahora bien, los tests son otra historia.Para demostrarlo, vamos a suponer que tenemos un componente muy sencillo que muestra un botón y un texto que cambia al hacer click sobre ese botón.Cuando interactuamos con este componente en el navegador, React se encarga de volver a renderizarlo (volver a ejecutar render) cuando necesita actualizar su estado, dando como resultado en este caso una actualización del DOM.Por el contrario, cuando renderizamos este componente en un test, React no espera que ocurran actualizaciones de estado entre lo que renderizamos inicialmente y las aserciones que hacemos sobre el DOM. Para entenderlo mejor, digamos que el trabajo de React en un test termina después de ejecutar el render. Y para terminar de endender el nombre de esa función act(), vamos a suponer que de las tres A (Arrange, Act y Assert) React solo espera que en un test ocurran la primera y la última:Normalmente en un test vamos a necesitar simular ciertos eventos para comprobar que el resultado de una interacción es el esperado. En este caso queremos comprobar que al hacer click sobre el botón, el texto cambia a "New text". Los métodos que Testing Library nos proporciona para simular las interacciones de usuario (fireEvent y userEvent) utilizan internamente act() y por eso no necesitamos usarlo en la mayoría de los casos. Esto es, en mi opinión, lo que contribuye a que no tengamos claro por qué a veces aparece ese warning, ya que no siempre es evidente que ya lo estamos usando.Para demostrar esto, en lugar de fireEvent o userEvent vamos a usar el método click() nativo del botón:El resultado de ejecutar este test será un warning de act() y un test fallido. Lo que React nos está diciendo con ese warning viene a ser algo así:¡Ey! Estás haciendo algo que actualiza el estado. Necesito que me avises para que pueda volver a renderizar el componente. De lo contrario no te puedo garantizar que estés probando lo que esperas.Y como hemos podido ver en este ejemplo, nos avisa por una buena razón: el DOM que estamos probando no está actualizado.Ahora que ya hemos entendido por qué aparece el warning, vamos a ver cómo solucionarlo. Siempre que hagamos algo en un test que provoque un cambio de estado, tenemos que envolverlo en act():O mucho mejor, utilizar los métodos que Testing Library nos proporciona para simular interacciones de usuario, que ya hacen uso de act() "under the hood":Ejemplo con fireEvent:Ejemplo con userEvent (asíncrono):No todas las actualizaciones de estado ocurren inmediatamente después de una interacción de usuario. En ocasiones, el estado se actualiza como respuesta a un evento asíncrono, como por ejemplo un setTimeout.Para ejemplificarlo, vamos a modificar un poco nuestro componente para que el texto cambie después de 1 segundo:En este caso, aunque usemos los métodos de Testing Library para simular la interacción de usuario, el test fallará porque el cambio de estado no ocurre inmediatamente como respuesta a un click, sino después de 1 segundo:Podemos sentir la tentación de solucionarlo usando las queries asíncronas de Testing Library, pero en ese caso no estaremos evitando que pase 1 preciado segundo en nuestro test:La ejecución de este test tarda más de 1 segundo. Lo normal y recomendable cuando usamos temporizadores en nuestros componentes, es "mockearlos" para evitar que ese tiempo se consuma realmente en nuestros tests. Para ello, Jest o Vi nos proporcionan el método useFakeTimers():Sin embargo, este test fallará con el mismo warning de act() que hemos visto anteriormente. Dado que la actualización de estado no ocurre como respuesta al onClick del botón, sino al callback del setTimeout, necesitamos avisar a React de que tiene que volver a renderizar el componente tras forzar el avance del temporizador.¡Y voilà! Nuestro test no solo pasa, sino que además su ejecución es mucho más rápida gracias a los fake timers.Siempre que en nuestros tests estemos provocando actualizaciones de estado, necesitamos avisar a React de que tiene que volver a renderizar el componente mediante act() si no estamos usando alguno de los métodos de Testing Library que lo hacen internamente, como fireEvent. Ignorar este warning puede provocar que nuestros tests no sean fiables (incluso cuando no fallen), ya que el DOM que estamos probando no está actualizado. Las queries asíncronas de Testing Library (findBy*) también usan act() internamente, pero no siempre son la solución adecuada, especialmente cuando usamos temporizadores en nuestros componentes que consumen tiempo real en nuestros tests.Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse vayola pradeep - Oct 14 Andrew Lee - Sep 22 Arthur Nascimento Assunção - Sep 25 Olasunkanmi Balogun - Oct 13 Once suspended, kuscamara will not be able to comment or publish posts until their suspension is removed. Once unsuspended, kuscamara will be able to comment and publish posts again. Once unpublished, all posts by kuscamara will become hidden and only accessible to themselves. If kuscamara is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Kus Cámara. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag kuscamara: kuscamara consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging kuscamara will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Testing de componentes React: ¿cuándo y por qué necesitamos usar act()?

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×