单元测试AngularJs Jasmine错误:已经调用了预期的间谍登录 [英] Unit Test AngularJs Jasmine error: Expected spy login to have been called

查看:178
本文介绍了单元测试AngularJs Jasmine错误:已经调用了预期的间谍登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是AngularJs和Jasmine的新测试。我正在尝试测试登录POST $ http服务。我不太确定该怎么做,但是我得到了一个错误,我不知道为什么。

I'm new testing with AngularJs and Jasmine. I'm trying to test a login POST $http service. I'm not pretty sure how to do it, but what I have I'm getting an error and I dont know why.

这是我的login.service.js :

This is my login.service.js:

(function () {
  'use strict';

  angular
    .module('app')
    .service('loginService', loginService);

  /** @ngInject */
  function loginService($http) {
    var url = 'http://localhost:8080/login';
    var service = {
      login: login
    };
    return service;

    // ////////// //
    function login(user) {
      return $http.post(url, user);
    }
  }
})();

这是我的测试:

describe('login component', function () {
  var loginService;
  var httpBackend;
  var user = {
    username: 'ADMIN',
    password: 'ADMIN'
  };

  beforeEach(module('app'));

  beforeEach(angular.mock.inject(function (_$httpBackend_, _loginService_) {
    loginService = _loginService_;
    httpBackend = _$httpBackend_;

  }));

  it('loginService should be defined', function () {
    expect(loginService).toBeDefined();
  });

  it('loginService.login should be defined', function () {
    expect(loginService.login).toBeDefined();
  });

  describe('We call the Login Service', function () {
    beforeEach(function () {
      spyOn(loginService, "login").and.callThrough();
    });
    it('we call the service', function () {
      loginService.login(user);
    });

    it('we look if we called the  login service', function () {
      expect(loginService.login).toHaveBeenCalled();
    });

    it('loginService login we send the correct parameters', function () {
      expect(loginService.login).toHaveBeenCalledWith('http://localhost:8080/login', 'POST', user);
    });
  });
});

运行时出现下一个错误:

I'm getting the next error when it runs:

PhantomJS 2.1.1 (Linux 0.0.0) login component We call the Login Service we look if we called the  login service FAILED
    Expected spy login to have been called.
    .tmp/app/login/login.spec.js:37:50
    loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Linux 0.0.0) login component We call the Login Service loginService login we send the correct parameters FAILED
    Error: <toHaveBeenCalledWith> : Expected a spy, but got Function.
    Usage: expect(<spyObj>).toHaveBeenCalledWith(...arguments) in node_modules/jasmine-core/lib/jasmine-core/jasmine.js (line 3340)
    .tmp/app/login/login.spec.js:41:54
    loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Linux 0.0.0): Executed 6 of 6 (2 FAILED) (0.041 secs / 0.046 secs)

有谁知道我做错了什么??

Does anybody know what I'm doing wrong??

谢谢!!!!

推荐答案

你是测试一切都错了。由于您正在测试 loginService login 是在该服务上定义的方法,因此您不应该模拟该方法 login

You're testing it all wrong. Since you're testing the loginService and login is a method defined on that service, you shouldn't mock the method login.

您应该只模拟不属于代码的方法(在这种情况下是一种服务) )你正在测试。所以根据这个,你应该嘲笑你在 $ http 服务上执行的 post 调用。

You should only be mocking methods that don't belong to the code(a service in this case) that you're testing. So according to this, you should be mocking the post call that you perform on the $http service.

这可以这样做:

describe('login component', function () {
    var loginService;
    var $httpBackend;
    var user = {
        username: 'ADMIN',
        password: 'ADMIN'
    };

    beforeEach(module('app'));

    beforeEach(angular.mock.inject(function (_$httpBackend_, _loginService_) {
        loginService = _loginService_;
        $httpBackend = _$httpBackend_;

        $httpBackend.whenPOST('http://localhost:8080/login', user).respond(201, 'SUCCESS');
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    /**
     * Ideally, these should be inside a seperate describe block.
     */
    // it('loginService should be defined', function () {
    //     expect(loginService).toBeDefined();
    // });

    // it('loginService.login should be defined', function () {
    //     expect(loginService.login).toBeDefined();
    // });

    //Like this.
    describe('Initialization', function(){
        it('loginService should be defined', function () {
            expect(loginService).toBeDefined();
        });

        it('loginService.login should be defined', function () {
            expect(loginService.login).toBeDefined();
        });
    });

    describe('function: login', function () {
        /*
         * We should not be spying a method from the service we're trying to test.
         * This is anti-pattern. We should be mocking the post call instead.
         */
        // beforeEach(function () {
        //     spyOn(loginService, "login").and.callThrough();
        // });

        /** 
         * This test is not doing anything. Each it block should have atleast one expect. 
         */
        // it('we call the service', function () {
        //     loginService.login(user);
        // });

        /**
         * This isn't what should be expected here. We should call the method and expect some response.
         * The response will be mocked by us using $httpBackend's expectPOST method. 
         */
        // it('we look if we called the  login service', function () {
        //     expect(loginService.login).toHaveBeenCalled();
        // });

        // it('loginService login we send the correct parameters', function () {
        //     expect(loginService.login).toHaveBeenCalledWith('http://localhost:8080/login', 'POST', user);
        // });
        it('should respond with status 201 and data \'SUCCESS\'', function(){
            var response = loginService.login(user);
            $httpBackend.flush();
            response.success(function(res){
                expect(res).toEqual("SUCCESS");
            });
        });
    });
});

现在你会发现我已经评论了你的大部分代码。这是因为所遵循的做法都是错误的。

Now you would find that I've commented most of your code. And that's because the practice that has been followed is all wrong.

应该遵循的做法是,你应该使用多个 describe 代码的不同部分的块。这就是我所做的。请仔细阅读我给出的评论。这将有助于您更好地理解。

The practice that should be followed is, you should be using multiple describe blocks for different parts of you code. That's what I've done. Please do go through the comments that I've given. That would help you understand better.

希望这会有所帮助!

这篇关于单元测试AngularJs Jasmine错误:已经调用了预期的间谍登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆