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 solicitudMockXhr
MockXhrServer
MockXhrServer
MockXhr
MockXhr
MockXhrRequest
newMockXhr()
newServer()
XMLHttpRequest
a 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.
onCreate
Mé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 ) => { /*...*/ } ;
onSend
Mé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.
body
El 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.
XMLHttpRequest
Basado 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