Estoy tratando de bloquear una función usando sinon. La función tiene la siguiente firma
export function getIndexDocument( svc: MetaHTTPService | ServiceConfig ): MetaPromise<RepoResponseResult<IndexDocument>> {¿Es esta la forma correcta de subtitularlo?
sandbox.stub(getIndexDocument).resolves({} as RepoResponseResult)Lo intenté pero me devuelve un error.
Así es como se llama esta función.
Tengo una clase llamada AssetsController con las siguientes funciones
public async exploreIndexDocument(): Promise<Asset | undefined> { // it makes an HTTP request and returns a promise that resolves with the following info { repoId: "", assetId: "" } const { result: { assignedDirectories } } = await getIndexDocument(this.serviceConfig).catch(err => { throw new Error(`Bad repsonse`); }); return { repoId: result.repoId; assetId: result.assetId } } public async function copyAsset(asset) { const res = await this.exploreIndexDocument(); const repoId = res.repoId; return asset.copy(repoId); }Estoy tratando de probar la función copyAsset, pero llama a exploreIndexDocument que llama a getIndexDocument. getIndexDocument se importa en la parte superior del archivo y reside en el módulo @ma/http. getIndexDocument realiza una solicitud HTTP.
¿Cómo puedo probar copyAsset dado que llama a getIndexDocument que realiza una solicitud HTTP?
Creo que la mayoría de sus problemas se pueden resolver revisando su arquitectura. Por ejemplo, en lugar de crear una dependencia explícita en getIndexDocument dentro de su clase AssetController , simplemente puede inyectarlo. Esto le permitirá intercambiar implementaciones según el contexto.
type IndexDocumentProvider = (svc: MetaHTTPService | ServiceConfig) => MetaPromise<RepoResponseResult<IndexDocument>>; interface AssetControllerOptions { indexDocumentProvider: IndexDocumentProvider } class AssetController { private _getIndexDocument: IndexDocumentProvider; public constructor(options: AssetControllerOptions) { this._getIndexDocument = options.indexDocumentProvider; } } Luego puede usar this._getIndexDocument en cualquier lugar y no preocuparse por cómo hacer que la implementación original se comporte como desea en sus pruebas. Simplemente puede proporcionar una implementación que haga lo que quiera.
describe('copyAsset', () => { it('fails on index document error.', () => { const controller = new AssetController({ indexDocumentProvider: () => Promise.reject(new Error(':(')); }); .... }); it('copies asset using repo id.', () => { const controller = new AssetController({ indexDocumentProvider: () => Promise.resolve({ repoId: "420" }) }); ... }); }); Obviamente, puede usar stubs en lugar de solo funciones o lo que sea si necesita algo elegante.
Arriba, eliminamos una dependencia explícita de una implementación y, en su lugar, la reemplazamos con un contrato que debe proporcionarse al controlador. Normalmente se denomina Inversion of Control e Dependency Injection .
De acuerdo con los documentos , no puede bloquear una función existente.
Puedes:
// Create an anonymous sstub function var stub = sinon.stub(); // Replaces object.method with a stub function. An exception is thrown // if the property is not already a function. var stub = sinon.stub(object, "method"); // Stubs all the object's methods. var stub = sinon.stub(obj);Lo que no puedes hacer es stub solo una función como:
var stub = sinon.stub(myFunctionHere);Esto tiene sentido porque si todo lo que tiene es una referencia a una función, entonces puede crear una nueva función para usar en su lugar, y luego pasarla a donde sea que su prueba la necesite.
Creo que solo quieres:
const myStub = sandbox.stub().resolves({} as RepoResponseResult) En su actualización, parece que desea colocar el código auxiliar en la clase AssetsController . Consulte esta respuesta para obtener más información al respecto, pero en este caso creo que desea:
const myStub = sandbox .stub(AssetsController.prototype, 'exploreIndexDocument') .resolves({} as RepoResponseResult) Ahora, cada vez que una instancia de AssetsController llama a su método exploreIndexDocument , se debe usar el código auxiliar en su lugar.