【问题标题】:How can I Unit Test Rest Angular Service and Controller?如何对 Rest Angular 服务和控制器进行单元测试?
【发布时间】:2016-02-20 02:51:10
【问题描述】:

用于 API 调用的静止角。

我的目标是通过调用控制器来编写单元测试用例并测试所有范围都已分配,带有 REST API 响应但不是 MOCK RESPONSE 的代码块。

Rest Angular 服务 :-

(function () {

    angular.module('movieApp').service('movieApiService', callMoviesApi);

    function callMoviesApi(Restangular) {
        this.getMyMovie= function (Id) {
            return  Restangular.one('movies/' + movieId).get().then(function(result){
                return result.plain();
            });
        };

        this.getMoviesList = function () {
            return Restangular.all('movies').getList().then(function(result){
              return result.plain();
            });
        };
    }

}());

我将此服务作为依赖项注入到控制器的位置 控制器代码如下:-

angular.module('movieApp').controller('MoviesController', ['$scope','movieApiService', 函数 ($scope, MovieService) {

    $scope.movie = $stateParams.movieId;

    MovieService.getMovieDetails($scope.movie).then(function (result) {
        $scope.movieDetails = result;
        $scope.movieId = result._id;
        $scope.movieName = result.displayName;
    });
}
]);

我确实尝试为上述控制器编写单元测试,但效果不佳:-(

测试代码如下:-

'use strict';

(function() {
    describe('MoviesController', function() {
        //Initialize global variables
        var scope,stateParams={},
            MoviesController;

        // Load the main application module
        beforeEach(module('movieApp'));

        beforeEach(inject(function($controller, $rootScope,$stateParams) {
            scope = $rootScope.$new();

            stateParams.movieId='Baahubali';

            HomeController = $controller('MoviesController', {
                $scope: scope,
                $stateParams:stateParams
            });
        }));

    it('Should call movieApi and Assign Scopes', function() {
          var Api="http://testsite.com/moives/thor";
          var myScope=$httpBackend.expectGET(Api).passthrough(); 
           expect(scope.movie).toBeDefined();
            console.log('****'+scope.movie.displayName);

            });
        });
    })();

错误正在引发:-

Error: Unexpected request: GET http://testsite.com/movies/undefined
        Expected GET http://testsite.com/movies/undefined? 
            at $httpBackend (C:/wrokingdir2015/public/lib/angular-mocks/angular-mocks.js:1245)
            at sendReq (C:/wrokingdir2015/public/lib/angular-mocks/public/lib/angular/angular.js:9695)

任何人都可以帮助我编写一个单元测试用例,它可以像在真实控制器中一样初始化控制器和分配范围进行测试。

老实说,我是单元测试的新人。

【问题讨论】:

    标签: angularjs rest unit-testing restangular angular-mock


    【解决方案1】:

    我建议 Selenium with Cucumber 让您测试的场景以一种美观易读的格式进行

    但如果只测试一个 REST api,你只需要一个 javax.ws.rs.client.Client 的实现,我使用 org.glassfish.jersey.client.JerseyClient。

    private final Client client = ClientBuilder.newClient();
    

    例如

        @When("^I want to retrieve all cells for the report with id \"([^\"]*)\".$")
        public void accessCellReport(String id) {
            response = client.target(URL).path(PathConstants.PATH_ID)
                             .resolveTemplate(PathConstants.PARAM_ID, reportId).request(MediaType.APPLICATION_JSON).get();
    
            RestAssertions.assertResponseOk(response);
        }
    

    【讨论】:

    • Hey Aurelius 你又来了 :-) 当然我想到了量角器,硒等。谢谢
    • 嗯,希望对你有帮助:)
    • 另一件事,要测试一个 rest api,你甚至不需要 selenium,一个 jersey 客户端就足够了,正如你在我发布的示例中看到的那样
    【解决方案2】:

    首先,我将使用 Restangulars 一种应该使用的方法。 在此处阅读更多信息:https://github.com/mgonto/restangular#creating-main-restangular-object

    Restangular.one('movies', movieId);
    

    在我的服务测试中,我会做这样的事情来测试是否调用了正确的端点。

    it('should call /movies/{movieId}', function() {
            var spy = sinon.spy(Restangular, 'one');
            var movieId = 1;
            movieApiService.getMyMovie(movieId);
            expect(spy).to.have.been.calledWith('movies', movieId);
    });
    

    然后我会制作一个 sinon 存根,以在控制器的另一个测试中模拟来自服务的响应。

    it('should set my movies variabel after calling movie service', function() {
            var mockResponse = [
                        {
                          id: 1,
                          title: 'Titanic'
                        },
                        {
                          id: 2,
                          title: 'American History X'
                        }
    
            ];
            sinon.stub(movieApiService, 'getMyMovie')
                 .returns(
                     $q.when(
                     [
                        {
                          id: 1,
                          title: 'Titanic'
                        },
                        {
                          id: 2,
                          title: 'American History X'
                        }
    
                     ]
                     );
                 );
                 expect($scope.movieList).to.equal(mockResponse);
    
    });
    

    还有另一个检查控制器 catch 函数是否被调用的测试。

    it('should call error handling if service rejects promise', function() {
            sinon.stub(movieApiService, 'getMyMovie')
                 .returns(
                     $q.reject('an error occured when fetching movie'); 
                 );
    });
    

    【讨论】:

      【解决方案3】:

      我建议使用 Selenium:

      http://www.seleniumhq.org/.

      易于编写单元测试,并且可以通过 jenkins build 实现自动化。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-27
        • 2013-07-27
        • 2023-03-12
        • 2012-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多