Eu tenho um aplicativo AngularJS configurado com testes usando Karma + Jasmine. Eu tenho uma função que quero testar que pega um objeto JSON grande, o converte em um formato que é mais consumível pelo resto do aplicativo e retorna esse objeto convertido. É isso aí.
Para meus testes, gostaria que você tivesse arquivos JSON separados (* .json) apenas com conteúdo JSON simulado - sem script. Para o teste, gostaria de poder carregar o arquivo JSON e bombear o objeto para a função que estou testando.
Eu sei que posso incorporar o JSON em uma fábrica de simulação, conforme descrito aqui: http://dailyjs.com/2013/05/16/angularjs-5/, mas eu realmente quero que o JSON não esteja contido no script - apenas JSON direto arquivos.
Eu tentei algumas coisas, mas sou bastante novato nesta área. Primeiro, configurei meu Karma para incluir meu arquivo JSON apenas para ver o que ele faria:
files = [
...
'mock-data/**/*.json'
...
]
Isso resultou em:
Chrome 27.0 (Mac) ERROR
Uncaught SyntaxError: Unexpected token :
at /Users/aaron/p4workspace4/depot/sitecatalyst/branches/anomaly_detection/client/anomaly-detection/mock-data/two-metrics-with-anomalies.json:2
Então eu mudei para apenas servir os arquivos e não "incluí-los":
files = [
...
{ pattern: 'mock-data/**/*.json', included: false }
...
]
Agora que eles estão apenas servidos, pensei em tentar carregar o arquivo usando $ http de dentro da minha especificação:
$http('mock-data/two-metrics-with-anomalies.json')
Quando executei a especificação, recebi:
Error: Unexpected request: GET mock-data/two-metrics-with-anomalies.json
O que, no meu entendimento, significa que espera uma resposta simulada de $ httpBackend. Então ... neste ponto eu não sabia como carregar o arquivo usando os utilitários Angular, então pensei em tentar o jQuery para ver se pelo menos conseguia fazer isso funcionar:
$.getJSON('mock-data/two-metrics-with-anomalies.json').done(function(data) {
console.log(data);
}).fail(function(response) {
console.log(response);
});
Isto resulta em:
Chrome 27.0 (Mac) LOG: { readyState: 4,
responseText: 'NOT FOUND',
status: 404,
statusText: 'Not Found' }
Eu inspeciono esta solicitação em Charles e está fazendo uma solicitação para
/mock-data/two-metrics-with-anomalies.json
Considerando que o resto dos arquivos que configurei para serem "incluídos" pelo Karma estão sendo solicitados em, por exemplo:
/base/src/app.js
Aparentemente, Karma está configurando algum tipo de diretório base para servir os arquivos. Então, para começar, alterei minha solicitação de dados jquery para
$.getJSON('base/mock-data/two-metrics-with-anomalies.json')...
E funciona! Mas agora me sinto suja e preciso tomar um banho. Ajude-me a me sentir limpo novamente.
fonte
Servir JSON por meio do dispositivo de fixação é o mais fácil, mas devido à nossa configuração, não poderíamos fazer isso facilmente, então escrevi uma função auxiliar alternativa:
Repositório
Instalar
$ bower install karma-read-json --save OR $ npm install karma-read-json --save-dev OR $ yarn add karma-read-json --dev
Uso
Coloque karma-read-json.js em seus arquivos Karma. Exemplo:
files = [ ... 'bower_components/karma-read-json/karma-read-json.js', ... ]
Certifique-se de que seu JSON está sendo servido pelo Karma. Exemplo:
files = [ ... {pattern: 'json/**/*.json', included: false}, ... ]
Use a
readJSON
função em seus testes. Exemplo:var valid_respond = readJSON('json/foobar.json'); $httpBackend.whenGET(/.*/).respond(valid_respond);
fonte
npm install karma-read-json
vez debower install karma-read-json
Tenho lutado para encontrar uma solução para carregar dados externos em meus casos de teste. O link acima: http://dailyjs.com/2013/05/16/angularjs-5/ Trabalhou para mim.
Algumas notas:
"defaultJSON" precisa ser usado como a chave em seu arquivo de dados fictício, isso é bom, pois você pode apenas referir-se a defaultJSON.
mockedDashboardJSON.js:
'use strict' angular.module('mockedDashboardJSON',[]) .value('defaultJSON',{ fakeData1:{'really':'fake2'}, fakeData2:{'history':'faked'} });
Então, em seu arquivo de teste:
beforeEach(module('yourApp','mockedDashboardJSON')); var YourControlNameCtrl, scope, $httpBackend, mockedDashboardJSON; beforeEach(function(_$httpBackend_,defaultJSON){ $httpBackend.when('GET','yourAPI/call/here').respond(defaultJSON.fakeData1); //Your controller setup .... }); it('should test my fake stuff',function(){ $httpBackend.flush(); //your test expectation stuff here .... }
fonte
parece que sua solução é a certa, mas há 2 coisas que eu não gosto nela:
Acabei de encontrar esse problema e tive que resolvê-lo rapidamente, pois não tinha mais tempo para o prazo, e fiz o seguinte
meu recurso json era enorme e não consegui copiar e colar no teste, então tive que mantê-lo em um arquivo separado - mas decidi mantê-lo como javascript em vez de json, e então simplesmente fiz:
var someUniqueName = ... the json ...
e eu incluí isso no karma conf includes ..
eu ainda posso simular uma resposta HTTP de back-end, se necessário com ele.
$httpBackend.whenGET('/some/path').respond(someUniqueName);
eu também poderia escrever um novo módulo angular a ser incluído aqui e, em seguida, alterar o recurso json para algo como
angular.module('hugeJsonResource', []).constant('SomeUniqueName', ... the json ... );
e simplesmente injete
SomeUniqueName
no teste, que parece mais limpo.talvez até embrulhe-o em um serviço
angular.module('allTestResources',[]).service('AllTestResources', function AllTestResources( SomeUniqueName , SomeOtherUniqueName, ... ){ this.resource1 = SomeUniqueName; this.resource2 = SomeOtherUniqueName; })
essa solução era mais rápida para mim, tão limpa e não exigia nenhuma nova curva de aprendizado. então eu prefiro este.
fonte
Eu estava procurando a mesma coisa. Vou tentar essa abordagem . Ele usa os arquivos de configuração para incluir os arquivos de dados fictícios, mas os arquivos são um pouco mais do que json, porque o json precisa ser passado para angular.module ('MockDataModule'). Value e então seus testes de unidade também podem carregar vários módulos e então o conjunto de valores está disponível para ser injetado na chamada beforeEach inject.
Também encontrei outra abordagem que parece promissora para solicitações xhr que não são caras, é um ótimo post que descreve o teste intermediário, que se bem entendi permite que seu controlador / serviço realmente recupere dados como em um teste e2e, mas seu teste intermediário tem acesso ao escopo do controlador (e2e não acho).
fonte
Existem pré-processadores Karma que funcionam com arquivos JSON também. Há um aqui:
https://www.npmjs.org/package/karma-ng-json2js-preprocessor
E plug sem vergonha, este é um que desenvolvi que tem suporte para RequireJS
https://www.npmjs.org/package/karma-ng-json2js-preprocessor-requirejs
fonte
Você pode usar o pré-processador karma-html2js para obter os arquivos json adicionados ao __html__ global.
veja esta resposta para obter detalhes: https://stackoverflow.com/a/22103160/439021
fonte
Aqui está uma alternativa à resposta de Cameron , sem a necessidade de
jasmine-jquery
nenhuma configuração extra do Karma, para testar, por exemplo, um serviço Angular usando$resource
:angular.module('myApp').factory('MyService', function ($resource) { var Service = $resource('/:user/resultset'); return { getResultSet: function (user) { return Service.get({user: user}).$promise; } }; });
E o teste de unidade correspondente:
describe('MyServiceTest', function(){ var $httpBackend, MyService, testResultSet, otherTestData ; beforeEach(function (done) { module('myApp'); inject(function ($injector) { $httpBackend = $injector.get('$httpBackend'); MyService = $injector.get('MyService'); }); // Loading fixtures $.when( $.getJSON('base/test/mock/test_resultset.json', function (data) { testResultSet = data; }), $.getJSON('base/test/mock/test_other_data.json', function (data) { otherTestData = data; }) ).then(done); }); it('should have some resultset', function() { $httpBackend.expectGET('/blahblahurl/resultset').respond(testResultSet); MyService.getResultSet('blahblahurl').then(function (resultSet) { expect(resultSet.length).toBe(59); }); $httpBackend.flush(); }); });
fonte