web-dev-qa-db-fra.com

Se moquer et tronquer avec un rapporteur

Je veux tester mon angular avec rapporteur. L'application a un module API qui parle au serveur Pendant ces tests, je veux me moquer de ce module Api. Je ne veux pas faire une intégration complète tests, mais des tests à partir de l'entrée utilisateur avec les valeurs attendues de l'API. Non seulement cela pourrait accélérer les tests du client, mais cela me permettrait également de tester les cas Edge, comme les erreurs de connexion.

Comment puis-je faire cela avec un rapporteur? Je viens de commencer à configurer les tests d'intégration.

J'ai utilisé le module rapporteur npm, installé Selenium, ajusté la configuration par défaut et utilisé le onProtractorRunner.js pour vérifier mes travaux de configuration.

Quelle est la manière recommandée de se moquer? Je suppose que la moquerie doit être effectuée dans le navigateur et non directement dans le fichier de test. Je suppose que les commandes du fichier de test sont spécifiques au rapporteur et seront envoyées aux coureurs Selenium. Par conséquent, je ne peux pas partager d'objets javascript pendant la session et le test.

Je m'attends en quelque sorte à avoir besoin d'une bibliothèque d'espionnage comme sinon.js ou est-ce déjà inclus dans le rapporteur?

Edit: J'ai lu ce problème dans le traqueur de problème du rapporteur , ce qui pourrait être un moyen de le faire. Fondamentalement, vous écrivez un module simulé dans le test, qui est envoyé pour être exécuté dans le navigateur/la portée des applications.

Edit: Voici des problèmes plus prometteurs. Le premier parle de ajout de Mocks à l'application Angular . Le second parle de se moquant du backend .

Cela a l'air vraiment sympa, dans ce cas, l'application Angular resterait dans sa forme d'origine. Cependant, cela ne fonctionne actuellement qu'avec les ng-scénarios obsolètes.

33
user524824

Ce billet de blog discute des scénarios d'utilisation avancés pour Protractor. Il couvre en particulier la méthode peu connue addMockModule() de l'objet navigateur Protractor. La méthode vous permet de créer angular dans Protractor (c.-à-d. Mocks ou stubs de votre module API) et les télécharger sur le navigateur pour remplacer l'implémentation réelle dans le contexte d'une spécification ou d'un ensemble donné de spécifications.

9

Vous n'avez pas accès à $ httpBackend, aux contrôleurs ou aux services à partir d'un test de rapporteur, donc l'idée est de créer un autre module angular et de l'inclure dans le navigateur pendant le test.

  beforeEach(function(){
    var httpBackendMock = function() {
      angular.module('httpBackendMock', ['ngMockE2E', 'myApp'])
        .run(function($httpBackend) {
          $httpBackend.whenPOST('/api/packages').respond(200, {} );
        })
    }
    browser.addMockModule('httpBackendMock', httpBackendMock)
  })

ngMockE2E vous permet de créer une fausse implémentation backend pour votre application. Voici un article plus approfondi sur le sujet http://product.moveline.com/testing-angular-apps-end-to-end-with-protractor.html

4
jvans

Bien que je ne l'ai pas essayé moi-même à ce stade, Angular fournit un faux $ httpBackend pour les tests E2E:

http://docs.angularjs.org/api/ngMockE2E/service/$httpBackend

Donc, d'après la page de documentation ci-dessus, je pense que vous pouvez utiliser quelque chose comme ce qui suit avant vos tests

beforeEach(function() {
  $httpBackend.whenGET('/remote-url').respond(edgeCaseData);
});
2
Michal Charemza

J'ai créé un petit module de simulation personnalisable pour m'aider à gérer les scénarios de réussite et d'erreur, peut-être qu'il vous aidera à mieux organiser la simulation.

https://github.com/unDemian/protractor-mock

1
unDemian

J'ai essayé de me moquer de certains services dans le rapporteur, et après avoir consulté certains blogs, je suis arrivé à une solution qui fonctionne pour moi. L'idée n'est pas de se moquer lourdement, il suffit de générer des réponses d'erreur; car pour les appareils, j'ai déjà une porte dérobée dans mon serveur API pour remplir le backend.

Cette solution utilise la $provide.decorator() pour simplement modifier certaines méthodes. Voici comment il est utilisé dans les tests:

it('should mock a service', function () {
    app.mock.decorateService({
        // This will return a rejected promise when calling to "user"
        // service "login()" method resolved with the given object.
        // rejectPromise() is a convenience method
        user: app.mock.rejectPromise('login', { type: 'MockError' }),

        // You can decorate the service
        // Warning! This code get's stringified and send to the browser
        // it does not have access to node
        api: function ($delegate, $q) {
            $delegate.get = function () {
                var deferred = $q.defer();

                deferred.resolve({ id: 'whatever', name: 'tess' });

                return defer.promise;
            };

            return $delegate;
        },

        // Internally decorateService converts the function to string
        // so if you prefer you can set an string. Usefull for creating your
        // own helper methods like "rejectPromise()".
        dialog: [
            "function ($delegate, $window) {",
                "$delegate.alert = $window.alert;",
                "return $delegate;",
            "}"
        ].join('\n')
    });

    // ...

    // Important!
    app.mock.clearDecorators();
});

Voici le code:

App.prototype.mock = {
    // This must be called before ".get()"
    decorateService: function (services) {
        var code = [
            'var decorer = angular.module("serviceDecorator", ["visitaste"]);',
            'decorer.config(function ($provide) {'
        ];

        for (var service in services) {
            var fn = services[service];

            if (_.isFunction(fn)) {
                code.Push('$provide.decorator("'+ service +'", '+ String(fn) +');');
            } else if (_.isString(fn)) {
                code.Push('$provide.decorator("'+ service +'", '+ fn +');');
            }
        }

        code.Push('});');

        browser.addMockModule('serviceDecorator', code.join('\n'));
    },
    clearDecorators: function () {
        browser.clearMockModules();
    },
    rejectPromise: function (method, error, delay) {
        return [
            'function ($delegate, $q) {',
                '$delegate.'+ method +' = function () {',
                    'var deferred = $q.defer();',
                    '',
                    'setTimeout(function () {',
                        'deferred.reject('+ JSON.stringify(error) +');',
                    '}, '+ (delay || 200) +');',
                    '',
                    'return deferred.promise;',
                '};',
                '',
                'return $delegate;',
            '}'
        ].join('\n');
    }
};
1
doup

Voici quelques options supplémentaires pour bloquer le serveur HTTP:

  • Stubby un petit serveur web avec prise en charge des nœuds, .Net et Java. Vous en aurez besoin pour vous installer et vous héberger.
  • Apiary un service hébergé pour créer de fausses API. Vous pouvez également l'utiliser pour créer de la documentation API.
0
Alexander Puchkov

Le point de l'exécution de tests de bout en bout avec rapporteur est de valider que l'application fonctionne en intégration. Si vous essayez de tester vos éléments d'interface utilisateur de manière isolée, il est plus facile d'utiliser de petits éléments provenant de tests normaux. Exactement comme AngularJS lui-même teste les directives.

Cela dit, si vous voulez vraiment vous moquer, une façon consiste à créer une version distincte de votre application avec des stubs au lieu de vrais services.

0
iwein