Error in mounted hook: "Reference Error: local Storage is not defined"솔루션

먼저 문제의 배경을 말하다.우선 Vue는 도망가지 않은 것이 틀림없다. 이 프로젝트에서 나는 전통적인(더 익숙해진) 자바스크립트를 사용하지 않고 TypeScript를 사용했고 모차+Chai를 도입했다. 정부에서 내놓은 Vue Test Utils와 결합하여 단원 테스트를 실시했다.Vue Test Utils는 사용하기 좋지만 아직 완전히 익지 않았기 때문인지 구덩이가 많다.나중에 한 편을 써서 나의 구덩이를 밟은 경험을 소개하다.
이번에 겪은 문제는 테스트 페이지(즉 .vue 파일)에서 Vue Test Utils의 mount/shallow Mount 방법을 사용하여 페이지를 만들었다는 것이다.페이지에서localStorage를 사용하여 일부 사용자 데이터를 액세스하기 때문에, 페이지는 시종 마운트할 수 없고, 오류가 발생했습니다. Error in mounted hook: "ReferenceError: localStorage is not defined솔직히 화면이 온통 빨갛게 달아오르는 것을 보면 짜증이 난다. 그러나 이 오보도 정상이다. 이론적으로 페이지에 호출된local Storage는window.localStorage이고 단원 테스트는 분명히 노드 환경에서 실행되고 노드 환경에는 윈도라는 전역 변수가 없다(대신 글로벌, 내가 앞서 언급한 바와 같이), 자연도 없다window.localStorage.vue-cli에 통합된 단원 테스트 플러그인@vue/cli-plugin-unit-mocha의 문서에서도 이 점을 명확하게 지적했다.
vue-cli-service test:unit
Run unit tests with mocha-webpack + chai.
Note the tests are run inside Node.js with browser environment simulated with JSDOM.
그러나 이곳의 환경은 조금 다르다. 전혀 없다window고 해도 옳지 않은 것 같다. 왜냐하면 여기에 JSDOM도 도입되었기 때문이다.JSDOM 이 패키지는 노드 환경에서 브라우저 환경을 모의하는 데 사용됩니다. window구체적인 사용 세부 사항은 스스로 문서를 조회할 수 있지만, 여기에 윈도우가 있다는 것만 명확히 하면 된다.
이론적으로, 우리는 윈도우에 local Storage를 추가하기만 하면 문제를 해결할 수 있다.먼저 설명하자면 다음은 모두 JS에 기초한 토론이다. 왜냐하면 이 라이브러리의 실현은 모두 JS이기 때문이다.그래서 일반적인 사고방식은 반드시 이와 같은 실현이다.
window.localStorage = {
    data: {},
    setItem(key, value) {
        this.data[key] = value;
    },
    getItem(key) {
        return this.data[key];
    }
};
// TypeError: Cannot set property localStorage of # which has only a getter

이런 작법은 비엄격한 모드에서는 침묵에 실패하고 엄격한 모드에서는 틀릴 수 있다.이것도 매우 재미있는 일이다. 왜냐하면 이곳의 window.localStorage 는 Getter만 있고 값을 부여할 수 없기 때문이다.그러니 우회해야 한다.
나중에 시험에서 나는 해결 방안을 얻었다. 먼저 dom-storage이라는 가방을 도입했고 dom-storage는 사실local Storage 기능을 실현했고 파일 읽기와 쓰기 기능을 제공했다.그리고 js 파일을 만듭니다. 예를 들어 localStorage.js 라고 부르십시오.
// localStorage.js
const Storage = require('dom-storage');
global.localStorage = new Storage(null, {strict: true});
window.localStorage = global.localStorage;

그리고 단원 테스트에 이 파일을 도입합니다.문제 해결.
기쁜 나머지 이 코드를 자세히 생각해 보면 수상한 점을 발견할 수 있다. window.localStorage 값을 부여할 수 없지 않습니까?코드를 바꾸자 바로 같은 오류가 발생했다.
// localStorage.js
'use strict';
const Storage = require('dom-storage');
global.localStorage = new Storage(null, {strict: true});
window.localStorage = global.localStorage;
// TypeError: Cannot set property localStorage of # which has only a getter

결론도 간단하다. 단원 테스트를 할 때 테스트 논리 호출은 global.localStorage이어야 한다.이 점을 검증하기 위해 페이지에console를 추가합니다.log, 출력은 다음과 같습니다.
// Test.vue
mounted() {
    console.log(localStorage);
}

// localStorage.js 
const Storage = require('dom-storage');
global.localStorage = new Storage(null, {strict: true});
window.localStorage = global.localStorage;
window.localStorage.setItem('test', 'test');
console.log(window.localStorage);
// Storage { test: 'test' }
// Storage {}

사실은 결국 문서에 있는 그 말로 돌아왔다.
Note the tests are run inside Node.js with browser environment simulated with JSDOM.
Node 환경에서 실행되는 한 글로벌과의 상호작용을 피할 수 없다.이렇게 한 바퀴 돌았는데 주로 JSDOM이 사람들에게 가져온 오해가 너무 깊어서 사람들이 노드에 윈도우를 만들었고 글로벌을 대체할 수 있다고 생각하게 한다.실은 그렇지 않다.
마지막으로 이 서류는 JS로 쓰는 것이 비교적 편리하다.TS는 온갖 방법을 다 동원하여 우리의 수정global을 방해할 것이기 때문에 이 작은 문제를 해결하기 위해 자체적으로 확장할 것이다.d.ts는 얻는 것보다 잃는 것이 많은 것 같다.TS에 JS를 섞는 건 좋지 않지만 문제를 해결할 수 있으니 이런 디테일을 신경 쓸 필요가 없다.
물론 굳이 쓰지 않아도 안 되는 것은 아니지만, 먼저 원래의 인터페이스를 확장해야 한다.
// shims-node.d.ts
declare namespace NodeJS {
    interface Global {
        localStorage: any
    }
}

// localStorage.ts
global.localStorage = {
    data: {},
    getItem(key: string) {
        return this.data[key];
    },
    setItem(key: string, value: string) {
        this.data[key] = value;
    }
};

끝.
이번에 단원 테스트를 쓰기 위해 이상한 버그가 많아지자 이를 보고도 좀 무감각해진 것 같은데...
모두가 알다시피 vue-cli3은 vue-cli2보다 훨씬 낫다. 더욱 간소화된 프로젝트 구조, 더욱 빠른 구축 속도, 고도의 추상적인 프로필, 더 많은 부합도가 높은 플러그인, 더욱 매끄러운 오픈 체험은 모두 사람을 편안하게 한다.좋은 점도 말하고 나쁜 점도 말한다. vue-cli3의 간결함은 사실 양날의 검으로 편리함과 동시에 버그를 숨기는 문제를 발견하기 어렵다.참으로 괴롭다.
그 전에 나는 또 다른 몇 가지 방안을 시험해 보았지만 모두 실패로 끝났고, 각종 이상한 문제가 발생했다.그중 가장 이상한 것은 사용mock-local-storage할 때 나온 것이다.이 패키지를 도입한 후(vue-cli3에서 프로젝트를 만들 때 단원 테스트를 선택하면 자체@vue/cli-plugin-unit-mocha;이 가방에는 jsdom-global이 도입되어 vue-cli-service test:unit --require jsdom-global --require mock-local-storage 호출을 통해 오류가 발생하고local Storage를 찾을 수 없습니다.vue-cli-service test:unit --require jsdom-global mock-local-storage로 바꾸면 다음과 같이 됩니다.
WEBPACK  Compiled successfully in xxxxms
MOCHA  Testing...
0 passing (0ms)
MOCHA  Tests completed successfully

테스트는 통과된 것 같았지만 실제로는 전혀 진행되지 않았다.호출 창고를 따라 추적해 내려가면 프로젝트 루트 디렉터리/node_modules/@vue/cli-plugin-unit-mocha/index.js의 60번째 줄(다른 프로젝트/시스템/IDE에 편차가 있을 수 있지만 이 줄 근처)에서 문제가 발견되고 이 줄hasInlineFilesGlob에는true가 부여되어 후속 테스트 논리가 바로 건너뜁니다.명령--require 뒤에 모듈을 초과할 때 이 논리를 촉발할 수 있기 때문이다.그런데 왜 이러는지 모르겠다.주로 경험이 얕아서 웹 패키지에 대해 잘 몰라요.따라서 일단 문제를 기록한 다음에 천천히 탐색하자.만약 아는 사람이 있다면 아낌없이 가르침을 주십시오.

좋은 웹페이지 즐겨찾기