我应该以角度模拟所有外部服务吗?

Isi*_*iel 4 unit-testing angularjs angularfire

我目前正在开始进行角度单元测试.作为我想要的第一个控制器看起来像这样,我感到困惑.

angular.module('sgmPaperApp')
  .controller('AccountCtrl', function ($mdToast, user, $firebaseArray, Ref) {
var vm = this;
vm.data = user;
vm.save = saveUser;
vm.comments = $firebaseArray(Ref.child('comments').orderByChild('person').equalTo(user.$id));


function saveUser() {
  vm.data.$save().then(function () {
    $mdToast.showSimple('Data saved');
  });
}
});
Run Code Online (Sandbox Code Playgroud)

我应该真的模仿我使用的所有外部服务吗?毕竟那个控制器不是很多,那么外部服务和嘲笑firebaseArray可能很困难.

感谢您的建议并帮助我开始测试

Phi*_*hil 5

您无需担心外部依赖项的作用,只需模拟其API即可.

这是我能看到的唯一的嘲笑.我假设你正在使用Jasmine

var Ref, $firebaseArray, $mdToast, user, vm;

beforeEach(function() {
    Ref = jasmine.createSpyObj('Ref', ['child', 'orderByChild', 'equalTo']);
    Ref.child.and.returnValue(Ref);
    Ref.orderByChild.and.returnValue(Ref);
    Ref.equalTo.and.returnValue(Ref);

    $firebaseArray = jasmine.createSpy('$firebaseArray').and.returnValue('comments');
    $mdToast = jasmine.createSpyObj('$mdToast', ['showSimple']);
    user = jasmine.createSpyObj('user', ['$save']);
    user.$id = 'id';

    module('sgmPaperApp'); // you should consider separate modules per "thing"

    inject(function($controller) {
        vm = $controller('AccountCtrl', {
            $mdToast: $mdToast,
            user: user,
            $firebaseArray: $firebaseArray,
            Ref: Ref
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以轻松创建测试

it('assigns a bunch of stuff on creation', function() {
    expect(vm.data).toBe(user);
    expect(vm.comments).toEqual('comments'); // that's what the mock returns

    expect(Ref.child).toHaveBeenCalledWith('comments');
    expect(Ref.orderByChild).toHaveBeenCalledWith('person');
    expect(Ref.equalTo).toHaveBeenCalledWith(user.$id);
    expect($firebaseArray).toHaveBeenCalledWith(Ref);
});
Run Code Online (Sandbox Code Playgroud)

你甚至可以测试基于promise的方法 saveUser

it('saves the user and makes some toast', inject(function($q, $rootScope) {
    user.$save.and.returnValue($q.when()); // an empty, resolved promise
    vm.saveUser();
    expect(user.$save).toHaveBeenCalled();
    expect($mdToast.showSimple).not.toHaveBeenCalled(); // because the promise hasn't resolved yet

    $rootScope.$apply(); // resolves promises

    expect($mdToast.showSimple).toHaveBeenCalledWith('Data saved');
}));
Run Code Online (Sandbox Code Playgroud)