source

각도에서의 $window.location.replace를 조롱하는 방법JS 유닛 테스트?

lovecheck 2023. 3. 18. 08:44
반응형

각도에서의 $window.location.replace를 조롱하는 방법JS 유닛 테스트?

다음과 같은 서비스를 받고 있습니다.

angular.module("services")
.factory("whatever", function($window) {
  return {
    redirect: function() {
      $window.location.replace("http://www.whatever.com");
    }
  };
});

조롱하는 방법$windowobject in unit test는 테스트 실행 시 페이지가 새로고침되지 않도록 합니다.

나는 그것을 사용해봤어요.

spyOn($window.location, 'replace').andReturn(true);

하지만 효과가 없었습니다(아직도)."Some of your tests did a full page reload!"에러) 및

$provide.value('$window', {location: {replace: jasmine.createSpy()}})

에러가 발생하고 있었습니다(Error: [ng:areq] Argument 'fn' is not a function, got Object스택 트레이스가 각진 자신의 소스만을 가리키고 있기 때문에 그다지 도움이 되지 않았습니다.

Chrome(다른 브라우저에서는 테스트하지 않음)에서는 location.replace가 읽기 전용이므로 spyOn에서 교체할 수 없습니다.

$provide.value작동해야 합니다.당신 코드 어딘가에 뭔가 잘못된 게 틀림없어요

여기 작업 단위 테스트가 있습니다.

describe('whatever', function() {
    var $window, whatever;

    beforeEach(module('services'));

    beforeEach(function() {
      $window = {location: { replace: jasmine.createSpy()} };

      module(function($provide) {
        $provide.value('$window', $window);
      });

      inject(function($injector) {
        whatever = $injector.get('whatever');
      });
    });

    it('replace redirects to http://www.whatever.com', function() {
      whatever.redirect();
      expect($window.location.replace).toHaveBeenCalledWith('http://www.whatever.com');
    });
});

저는 더 쉽지만 덜 우아한 해결책을 택할 것입니다.$window.location에 대한 래퍼를 작성하고 있습니다.이 래퍼는 모킹할 수 있습니다.당신의 코드에 관해서는 $window(여기에서는 당신의 실제 기능이 더 복잡하다고 가정합니다)가 아니라 whattery.redirect 함수를 비웃는 것입니다.

결국엔 다음과 같은 결과가...

angular.module("services")
.factory("whatever", function($window) {
  return {
    do_stuff_that_redirects: function() {
      lots of code;
      this.redirect("http://www.whatever.com");
      maybe_more_code_maybe_not;
    },

    redirect: function(url) {
      $window.location.replace(url);
    }
  };
});

리다이렉트 메서드를 직접 조롱할 수 있습니다.또한 코드 행이1개밖에 없기 때문에 문제가 발생하지 않는다고 믿을 수 있습니다.

spyOn(whatever, 'redirect').andCallFake(function(){});
expect(whatever.redirect).toHaveBeenCalledWith('http:/my.expected/url');

이것으로 충분하며, 호출된 URL을 검증할 수 있습니다.

당신에게 도움이 될 만한 다른 방법을 제시하겠습니다.궁극적으로 사용자를 리다이렉트하는 컨트롤러의 '액션'을 유닛에서 테스트하는 동안 동일한 문제에 직면했습니다(전체 페이지 로드, 그러나 더 큰 웹 사이트/애플리케이션의 다른 페이지로 이동).콘텍스트를 제공하기 위해 컨트롤러는 AJAX 요구를 실행합니다.응답이 정상일 경우 $window.location.replace()를 통해 사용자를 다른 페이지로 리다이렉트합니다.

$http.post('save', data)
        .success(function(responseData, status, headers, config) {
            if(responseData.redirect) {
                $window.location.replace(responseData.redirect);
            }
        })
        .error(function(responseData, status, headers, config) {
             console.error("ERROR while trying to create the Event!!");
        });

이 컨트롤러 기능의 테스트에서는 "Some your tests do full page reload!"라는 동일한 오류가 발생했습니다.그래서 컨트롤러 사양의 beforeEach() 함수에 $window 서비스를 mockout하기 위해 다음 사항을 추가했습니다.

mockWindow = { location: { replace: function(url) { console.log('redirecting to: ' + url); } } };
eventCtrl = $controller('EventCtrl', { $scope: scope, $window: mockWindow });

물론 이 솔루션에서는 replace 함수가 예상된 인수로 호출되었는지(정확하게) 확인할 수 없지만, 지금은 별로 신경 쓰지 않습니다.도움이 됐으면 좋겠다.

제 생각에 당신이 원하는 은 $location 서비스를 이용하는 것입니다.$window.location이 기능에 대해 설명하는 페이지도 있습니다.http://docs.angularjs.org/guide/dev_guide.services.$location

이것을 사용하면 테스트에서 $location 서비스의 stubbed 버전을 사용하는 것이 매우 간단할 것입니다.

$location.path('/someNewPath');

$location.replace(); // 또는 $location.path('/some New Path').replace();

언급URL : https://stackoverflow.com/questions/20252382/how-to-mock-window-location-replace-in-angularjs-unit-test

반응형