Esta biblioteca es una simulación de XMLHttpRequest que proporciona una interfaz simple para simular interacciones con XMLHttpRequest . Es un reemplazo directo de XMLHttpRequest para sus pruebas.
Esta biblioteca implementa la interfaz XMLHttpRequest y maneja solicitudes y eventos según lo especificado en la especificación XMLHTTPRequest sin utilizar solicitudes de red reales. Puedes responder a las solicitudes simuladas de tres maneras:
Puede simular respuestas, cargar progreso, errores y otras interacciones con los métodos de respuesta simulados. Estos manejan automáticamente el procesamiento de nivel inferior, como la emisión de eventos y el cambio de la propiedad readystate de XMLHttpRequest .
MockXhr mediante programacióntimeout y los tiempos de espera de solicitudMockXhrMockXhrServerMockXhrServerMockXhrMockXhrMockXhrRequestnewMockXhr()newServer()XMLHttpRequesta través de npm (administrador de paquetes de nodos)
$ npm install mock-xmlhttprequest
import { newServer } from 'mock-xmlhttprequest' ;
import { functionToTest } from '../src/SomethingToTest' ;
// Adapt based on your testing framework. This example uses Mocha and Chai's syntax.
it ( 'should produce a success response' , async ( ) => {
const server = newServer ( {
get : [ '/my/url' , {
// status: 200 is the default
headers : { 'Content-Type' : 'application/json' } ,
body : '{ "message": "Success!" }' ,
} ] ,
} ) ;
try {
// Installs the server's XMLHttpRequest mock in the "global" context.
// After this, "new XMLHttpRequest()" creates a mock request to which the server replies.
server . install ( /* optional context; defaults to globalThis */ ) ;
// Do something that send()s an XMLHttpRequest to '/my/url' and returns a Promise
// that resolves to the parsed JSON response
const result = await functionToTest ( ) ;
assert . equal ( result . message , 'Success!' ) ;
} finally {
// Restore the original XMLHttpRequest
server . remove ( ) ;
}
} ) ; La clase simulada XMLHttpRequest es MockXhr . Expone la misma interfaz que XMLHttpRequest y es un reemplazo directo para probar el código que usa XMLHttpRequest .
Hay dos opciones para controlar el comportamiento de las instancias MockXhr :
XMLHttpRequest . Úselo si necesita más control sobre las solicitudes sin las funciones proporcionadas por el servidor simulado. La clase MockXhrServer implementa el servidor simulado. Creas un MockXhrServer con newServer . MockXhrServer responde automáticamente a las solicitudes MockXhr y facilita la redacción de pruebas.
La estructura básica de las pruebas que utilizan MockXhrServer es:
import { newServer } from 'mock-xmlhttprequest' ;
const server = newServer ( /* routes */ ) ;
try {
server . install ( /* optional context; defaults to globalThis */ ) ;
// Test your code that creates XMLHttpRequests
} finally {
// Reverts server.install() at the end of the test.
// Only do this after the test case has finished creating XMLHttpRequests.
server . remove ( ) ;
} Hay dos enfoques para hacer que su código utilice la clase MockXhr como reemplazo de XMLHttpRequest . Esto permite que MockXhrServer responda a las solicitudes:
install() para reemplazar globalmente la clase XMLHttpRequest con la clase MockXhr del servidor. Al final del caso de prueba, llame remove() para restaurar el estado original.XMLHttpRequest , use la clase MockXhr directamente con una de las siguientes propiedades MockXhrServer :xhrFactory es una función que crea una instancia MockXhr .MockXhr es la clase de las instancias creadas por xhrFactory . Este código demuestra el uso de xhrFactory :
import { newServer } from 'mock-xmlhttprequest' ;
const server = newServer ( /* routes */ ) ;
const savedFactory = MyClass . xhrFactory ;
try {
MyClass . xhrFactory = server . xhrFactory ;
// Test code that creates XMLHttpRequests through MyClass.xhrFactory()
} finally {
// Only do this after the test case has finished creating XMLHttpRequests.
MyClass . xhrFactory = savedFactory ;
} Las rutas definen cómo responde MockXhrServer a las solicitudes MockXhr . Estos tienen tres partes:
Cuando envía una solicitud MockXhr , MockXhrServer encuentra la primera ruta que coincide con el método y la URL de la solicitud. Luego responde con el controlador de solicitudes de la ruta. También puede configurar un controlador de solicitudes predeterminado. Los controladores de solicitudes se definen mediante declaración o programación.
De forma predeterminada, si el atributo timeout de una solicitud se establece en un valor distinto de cero y MockXhrServer no responde a la solicitud, eventualmente se agota el tiempo de espera.
Hay dos formas de agregar rutas al MockXhrServer :
routes del newServer .MockXhrServer que agregan rutas. MockXhrServer registra todas las solicitudes de MockXhr que recibe en un registro de solicitudes. Úselo para validar las solicitudes XMLHttpRequest que envía su código.
MockXhrServer puede generar eventos de progreso de solicitud (carga) y respuesta (descarga) automáticamente. Esto está deshabilitado de forma predeterminada. Utilice el campo progressRate para habilitar esto.
También puede generar eventos de progreso si responde a las solicitudes de MockXhr mediante programación con un controlador de solicitudes de tipo Function .
Las respuestas a las solicitudes MockXhr son asincrónicas. Esto reproduce cómo funciona una solicitud XMLHttpRequest real. Por lo tanto, lo más probable es que necesite utilizar el soporte de prueba asincrónico de su marco de prueba. Por ejemplo, la documentación relevante para el marco de prueba de Mocha está aquí.
El enlace del ciclo de vida onSend es necesario para responder a las solicitudes MockXhr . El servidor simulado maneja esto automáticamente. La otra opción es utilizar directamente los enlaces del ciclo de vida MockXhr . En ambos casos, el enlace del ciclo de vida onSend se ejecuta después de que finaliza o se borra el contexto de ejecución que llama a XMLHttpRequest.send() . Internamente, esta biblioteca utiliza una Promise resuelta inmediatamente para obtener una pila de llamadas vacía.
MockXhr mediante programación Existen varios métodos y propiedades MockXhr para responder a las solicitudes. Estos métodos permiten las siguientes interacciones:
Consulte la sección Métodos de respuesta simulados para obtener más detalles.
timeout y los tiempos de espera de solicitud De forma predeterminada, si configura el atributo timeout de XMLHttpRequest en su código, las solicitudes de MockXhr expiran automáticamente después del retraso especificado. Esto emite el evento timeout y cancela la solicitud como se describe en la especificación.
Depender del paso del tiempo para probar cómo el código maneja los tiempos de espera generalmente hace que las pruebas sean frágiles y difíciles de depurar. En su lugar, puede activar tiempos de espera mediante programación con setRequestTimeout() .
Deshabilite los tiempos de espera automáticos de solicitudes con una de estas opciones:
disableTimeout() en un MockXhrServer . Esto afecta a todas las instancias MockXhr que maneja.MockXhr.timeoutEnabled = false . Esta propiedad estática de la clase MockXhr afecta a cada una de sus instancias.timeoutEnabled en false en una instancia MockXhr . Esto afecta sólo a esa instancia.MockXhr Este es un patrón de uso alternativo que no utiliza MockXhrServer . En su lugar, utiliza directamente los enlaces del ciclo de vida MockXhr . Esto requiere más código, pero tienes más control sobre las solicitudes de MockXhr .
Tenga en cuenta que también puede utilizar los enlaces del ciclo de vida MockXhr junto con MockXhrServer si solo necesita ampliar el servidor simulado.
Ejemplo:
import { newMockXhr } from 'mock-xmlhttprequest' ;
import { functionToTest } from '../src/SomethingToTest' ;
// Adapt based on your testing framework. This example uses Mocha and Chai's syntax.
it ( 'should produce a success response' , async ( ) => {
// Get a "local" MockXhr subclass
const MockXhr = newMockXhr ( ) ;
// Mock JSON response
MockXhr . onSend = ( request ) => {
const responseHeaders = { 'Content-Type' : 'application/json' } ;
const response = '{ "message": "Success!" }' ;
request . respond ( 200 , responseHeaders , response ) ;
} ;
try {
// Install in the global context so "new XMLHttpRequest()" creates MockXhr instances
global . XMLHttpRequest = MockXhr ;
// Do something that send()s an XMLHttpRequest to '/my/url' and returns a Promise
// that resolves to the parsed JSON response
const result = await functionToTest ( ) ;
assert . equal ( result . message , 'Success!' ) ;
} finally {
// Restore the original XMLHttpRequest
delete global . XMLHttpRequest ;
}
} ) ; MockXhrServer Esta clase es un servidor simulado que responde a las solicitudes MockXhr en función de su URL y método.
MockXhrServer MockXhrServer(routes)Argumentos:
routes : Objeto con el conjunto inicial de rutas del servidor. (opcional) En la mayoría de los casos deberías usar newServer en lugar de este constructor directamente.
Las claves del objeto routes son métodos HTTP. Los valores son matrices con dos elementos: [url_matcher, request_handler] .
Consulte también Solicitar comparador de URL y Solicitar controlador.
Ejemplo:
const handlerFn = ( request ) => { request . respond ( ) ; } ;
newServer ( {
get : [ '/get' , { status : 200 } ] ,
'my-method' : [ '/my-method' , { status : 201 } ] ,
post : [ '/post' , [ handlerFn , { status : 404 } ] ] ,
} ) ; install(context = globalThis)Argumentos:
context : si proporciona un valor, el método install establece la propiedad XMLHttpRequest en este contexto en lugar del contexto global. (opcional) Instala el simulacro MockXhr del servidor en el contexto global para reemplazar la clase XMLHttpRequest . Revertir con remove().
remove()Devierte los cambios realizados por install(). Llame a esto después de sus pruebas.
progressRate Si configura progressRate en un number mayor que 0, el servidor genera automáticamente eventos de progreso de solicitud (carga) y respuesta (descarga). Cada evento de progreso aumenta en bytes progressRate .
progressRate solo se aplica a controladores de solicitudes de tipo object .
disableTimeout() y enableTimeout() Estos métodos deshabilitan o habilitan los efectos del atributo timeout de MockXhr . Consulte "El atributo timeout y los tiempos de espera de solicitud".
Las rutas configuran cómo el servidor responde a las solicitudes de MockXhr . Sus tres partes se describen a continuación.
El concepto de ruta se basa libremente en el marco Express.
Se permite cualquier string con un método de solicitud HTTP válido. Los métodos válidos incluyen métodos estándar como GET , POST , PUT y DELETE , así como otros nombres de métodos. Los nombres de los métodos estándar no distinguen entre mayúsculas y minúsculas.
El comparador de URL de solicitud puede ser uno de estos tipos:
string (por ejemplo '/my-url' ) que coincida exactamente con la URL de la solicitud.RegExp que coincida con la URL de la solicitud.Function que devuelve true si la URL de la solicitud coincide. La función recibe la URL como argumento. El controlador de solicitudes puede ser uno de estos tipos:
Un object con las propiedades de respuesta. Los valores predeterminados son:
{ status: 200, headers: {}, body: null, statusText: 'OK' }
Una Function que llama directamente a los métodos de respuesta simulados. La función recibe una instancia MockXhrRequest como argumento.
Una string con el valor 'error' o 'timeout' . Esto desencadena un error o un tiempo de espera respectivamente.
Una matriz de los otros tipos de controladores de solicitudes anteriores. La primera solicitud obtiene el primer controlador, la segunda obtiene el segundo controlador y así sucesivamente. El último controlador se reutiliza cuando no hay más controladores en la matriz.
Para los controladores de solicitudes object , el servidor agrega automáticamente el encabezado de respuesta Content-Length con la longitud del cuerpo de la respuesta.
Todos estos controladores son equivalentes:
const handlerObj = { } ;
const handlerFn = ( request ) => { request . respond ( 200 , { 'Content-Length' : '0' } ) ; } ;
const handlerArray = [ { } ] ; get(urlMatcher, handler)Argumentos:
urlMatcher : Solicitar comparador de URL.handler : controlador de solicitudes. Agrega una ruta para el método GET HTTP.
post(urlMatcher, handler)Argumentos:
urlMatcher : Solicitar comparador de URL.handler : controlador de solicitudes. Agrega una ruta para el método POST HTTP.
put(urlMatcher, handler)Argumentos:
urlMatcher : Solicitar comparador de URL.handler : controlador de solicitudes. Agrega una ruta para el método PUT HTTP.
delete(urlMatcher, handler)Argumentos:
urlMatcher : Solicitar comparador de URL.handler : controlador de solicitudes. Agrega una ruta para el método DELETE HTTP.
addHandler(method, urlMatcher, handler)Argumentos:
method : método HTTP como una string .urlMatcher : Solicitar comparador de URL.handler : controlador de solicitudes. Agrega una ruta para el method método HTTP.
setDefaultHandler(handler)Argumentos:
handler : controlador de solicitudes.Establece un controlador de solicitudes predeterminado para solicitudes que no coinciden con ninguna ruta.
setDefault404()Establece un controlador de solicitudes predeterminado que devuelve respuestas 404.
xhrFactory Función que devuelve una nueva instancia MockXhr .
MockXhr La clase MockXhr a la que se conecta el servidor. xhrFactory crea instancias de esta clase.
getRequestLog()Devuelve una matriz de todas las solicitudes recibidas por el servidor hasta el momento. Cada llamada devuelve una nueva matriz. Cada elemento de la matriz es un objeto con estas propiedades:
method : string del método HTTP.url : string de URL.body : cuerpo de la solicitudheaders : solicita encabezados como un objeto. Los nombres de los encabezados están en minúsculas.MockXhr Esta clase es una simulación de XMLHttpRequest . Esta sección documenta sus métodos y propiedades que no están en la especificación.
MockXhr.timeoutEnabled Esta propiedad boolean estática controla el tiempo de espera automático de las solicitudes de todas las instancias de la clase.
timeoutEnabled Esta propiedad boolean controla el tiempo de espera automático de esta instancia MockXhr .
getResponseHeadersHash()Devuelve todos los encabezados de respuesta como un objeto. Los nombres de los encabezados están en minúsculas.
MockXhr Puede definir métodos de devolución de llamada para los enlaces del ciclo de vida MockXhr en estas ubicaciones:
MockXhr . El gancho se aplica a todas las instancias de MockXhr y sus subclases.MockXhr devuelta por MockXhrServer.MockXhr o newMockXhr() . El gancho se aplica a todas las instancias de esa clase.MockXhr . El gancho se aplica sólo a esa instancia.Si define varios enlaces para un evento del ciclo de vida, se llaman en el orden anterior.
Generalmente debería preferir la tercera opción, que facilita el aislamiento de los casos de prueba.
onCreateMétodo de devolución de llamada que recibe estos argumentos:
xhr : Nueva instancia MockXhr . Utilice este enlace de ciclo de vida para interceptar instancias de MockXhr cuando se construyan.
Se llama cuando se crea una instancia de MockXhr , al final de su constructor. Por lo tanto, este enlace de ciclo de vida solo está disponible como propiedad estática.
import { MockXhr , newMockXhr } from 'mock-xmlhttprequest' ;
// Called for all instances of MockXhr and all its subclasses
MockXhr . onCreate = ( xhr ) => { /*...*/ } ;
// Called for all instances of this MockXhr subclass
const MockXhrSubclass = newMockXhr ( ) ;
MockXhrSubclass . onCreate = ( xhr ) => { /*...*/ } ; onSendMétodo de devolución de llamada que recibe estos argumentos:
request : MockXhrRequest para la solicitud.xhr : la instancia MockXhr .Utilice este enlace de ciclo de vida para responder a una solicitud con métodos de respuesta simulados.
Se llama de forma asíncrona después de cada llamada a send() . Cada llamada a send() genera una llamada a onSend con una instancia separada de MockXhrRequest .
import { MockXhr , newMockXhr } from 'mock-xmlhttprequest' ;
// Called for all instances of MockXhr and all its subclasses
MockXhr . onSend = ( request ) => { /*...*/ } ;
// Called for all instances of this MockXhr subclass
const MockXhrSubclass = newMockXhr ( ) ;
MockXhrSubclass . onSend = ( request ) => { /*...*/ } ;
// Called for this instance only
const xhr = new MockXhrSubclass ( ) ;
xhr . onSend = ( request ) => { /*...*/ } ;MockXhrRequest Cada llamada a send() crea un MockXhrRequest que contiene información sobre XMLHttpRequest y proporciona métodos para responder mediante programación.
requestHeaders Un HeadersContainer que contiene una copia de los encabezados de la solicitud.
method Una string con el método HTTP de la solicitud.
url Una string con la URL de la solicitud.
bodyEl cuerpo de la solicitud.
withCredentials Un valor boolean con el valor withCredentials de la solicitud.
getRequestBodySize() number de bytes en el cuerpo de la solicitud.
Nota: esto no es completamente exacto cuando el body es un FormData codificado con multipart/form-data . No se consideran los encabezados, la codificación y otros factores que contribuyen al tamaño real body de una XMLHttpRequest no simulada. Puede utilizar este método para obtener un valor mínimo para el tamaño real body de la solicitud. Esto es útil para simular eventos de progreso de carga.
Estos métodos proporcionan una interfaz programática para responder a las solicitudes de MockXhr .
Si una llamada a un método de respuesta no es válida, genera un Error con un mensaje que contiene "Mock usage error detected" .
uploadProgress(transmitted)Argumentos:
transmitted : number de bytes transmitidos.Activa una solicitud de progreso de carga.
Solo puedes llamar a esto cuando el body de la solicitud no sea null y la carga no esté completa.
Después de llamar a este método, puede utilizar cualquier otro método de respuesta simulada.
respond(status = 200, headers = {}, body = null, statusText = 'OK')Argumentos:
status : number de estado HTTP de respuesta. (opcional)headers : object con los encabezados de respuesta. (opcional)body : Cuerpo de respuesta. (opcional)statusText : texto de estado HTTP de respuesta string . (opcional) Método de respuesta completo que establece tanto los encabezados como el cuerpo de la respuesta. Cambia el readyState de la solicitud a DONE .
Activa los eventos apropiados, como readystatechange , progress y load .
Esta es una abreviatura de setResponseHeaders() seguido de setResponseBody() .
Después de llamar a este método, no podrá utilizar otros métodos de respuesta simulados. Esta restricción se elimina si vuelve a llamar open() .
setResponseHeaders(status = 200, headers = {}, statusText = 'OK')Argumentos:
status : number de estado HTTP de respuesta. (opcional)headers : object con los encabezados de respuesta. (opcional)statusText : texto de estado HTTP de respuesta string . (opcional) Establece los encabezados de respuesta. Cambia el readyState de la solicitud a HEADERS_RECEIVED .
Activa los eventos apropiados, como readystatechange , progress y load .
Después de llamar a este método, puede utilizar los siguientes métodos de respuesta simulados:
downloadProgress()setResponseBody()setNetworkError()setRequestTimeout() . downloadProgress(transmitted, length)Argumentos:
transmitted : number de bytes transmitidos.length : number de bytes en la respuesta. Activa un evento de progreso de respuesta. Cambia el readyState de la solicitud a LOADING si es HEADERS_RECEIVED .
Debes llamar setResponseHeaders() antes de este método.
setResponseBody(body = null)Argumentos:
body : cuerpo de respuesta. (opcional) Establece el cuerpo de la respuesta. Cambia el readyState de la solicitud a DONE .
Activa los eventos apropiados, como readystatechange , progress y load .
Llama setResponseHeaders() si aún no se ha llamado. Los encabezados de respuesta solo contienen Content-Length con un valor igual a la longitud del cuerpo de la respuesta.
Después de llamar a este método, no podrá utilizar otros métodos de respuesta simulados. Esta restricción se elimina si vuelve a llamar open() .
setNetworkError() Simula un error de red. Cambia el readyState de la solicitud a DONE .
Activa los eventos apropiados, incluido el evento error .
Después de llamar a este método, no podrá utilizar otros métodos de respuesta simulados. Esta restricción se elimina si vuelve a llamar open() .
setRequestTimeout() Simula un tiempo de espera de solicitud. Cambia el readyState de la solicitud a DONE .
Activa los eventos apropiados, incluido el evento timeout .
Genera un error si el atributo request es igual a 0 ya que en ese caso no se producen tiempos de espera.
Después de llamar a este método, no podrá utilizar otros métodos de respuesta simulados. Esta restricción se elimina si vuelve a llamar open() .
newMockXhr() Devuelve una nueva subclase MockXhr .
Si utiliza una subclase diferente de MockXhr en cada caso de prueba, es más fácil asegurarse de que sean independientes. Por ejemplo, si establece la propiedad estática timeoutEnabled en una subclase, solo afectará a esa subclase y no a las otras subclases creadas en otros casos de prueba. Dado que las subclases no se reutilizan, no se requiere código de limpieza que revierta los cambios realizados en una subclase.
newServer(routes)Argumentos:
routes : Objeto con el conjunto inicial de rutas del servidor. (opcional) Devuelve un nuevo MockXhrServer con su propia subclase MockXhr única. Ver newMockXhr() .
Agregue rutas al MockXhrServer con el argumento routes opcional. Consulte al constructor para obtener más detalles.
XMLHttpRequestBasado en la versión de especificación XMLHTTPRequest '15 de agosto de 2022'.
open() , setRequestHeader() , send() y abort() .statusText , encabezados y cuerpo.timeout (se puede desactivar).MockXhr.setNetworkError() ).MockXhr.setRequestTimeout() ).overrideMimeType() se lanza cuando es necesario, pero no tiene ningún otro efecto.responseType : '' , 'text' y 'json' son totalmente compatibles. Los valores responseType no tienen ningún efecto en el cuerpo de la respuesta pasado a setResponseBody() .responseXml : el cuerpo de la respuesta no se convierte en una respuesta de documento. Para obtener una respuesta de documento, pásela directamente como cuerpo de respuesta en setResponseBody() .responseUrl : la URL de solicitud final después de las redirecciones no se establece automáticamente. Esto se puede emular en un controlador de solicitudes.async configurado en false en open() ).open() y lanzar SyntaxError en caso de error. ¡Los contribuyentes son bienvenidos! Consulte esta guía para obtener más información.
MIT