Câu trả lời:
Giải pháp tuyệt vời từ @chiedo
Tuy nhiên, chúng tôi sử dụng cú pháp ES2015 và tôi cảm thấy nó gọn gàng hơn khi viết theo cách này.
class LocalStorageMock {
constructor() {
this.store = {};
}
clear() {
this.store = {};
}
getItem(key) {
return this.store[key] || null;
}
setItem(key, value) {
this.store[key] = value.toString();
}
removeItem(key) {
delete this.store[key];
}
};
global.localStorage = new LocalStorageMock;
|| null
là lý do tại sao bài kiểm tra của tôi thất bại, bởi vì trong bài kiểm tra của tôi, tôi đã sử dụng not.toBeDefined()
. Giải pháp @Chiedo làm cho nó hoạt động trở lại
Tìm ra nó với sự giúp đỡ từ điều này: https://groups.google.com/forum/#!topic/jestjs/9EPhuNWVYTg
Thiết lập một tệp với các nội dung sau:
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key];
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
},
removeItem: function(key) {
delete store[key];
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
Sau đó, bạn thêm dòng sau vào gói.json theo cấu hình Jest của bạn
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
"setupFiles": [...]
làm việc tốt Với tùy chọn mảng, cho phép tách các giả thành các tệp riêng biệt. Ví dụ:"setupFiles": ["<rootDir>/__mocks__/localStorageMock.js"]
getItem
hơi khác với giá trị mà trình duyệt sẽ trả về nếu không có dữ liệu nào được đặt theo một khóa cụ thể. gọi getItem("foo")
khi nó không được đặt sẽ trở lại null
trong trình duyệt, nhưng undefined
bằng giả này - điều này đã khiến một trong những thử nghiệm của tôi thất bại. Giải pháp đơn giản đối với tôi là trở lại store[key] || null
trong getItem
chức năng
localStorage['test'] = '123'; localStorage.getItem('test')
Nếu sử dụng ứng dụng tạo phản ứng, có một giải pháp đơn giản và dễ hiểu hơn được giải thích trong tài liệu .
Tạo src/setupTests.js
và đặt cái này trong đó:
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
clear: jest.fn()
};
global.localStorage = localStorageMock;
Tom Mertz đóng góp trong một bình luận dưới đây:
Sau đó, bạn có thể kiểm tra các hàm localStorageMock của mình được sử dụng bằng cách thực hiện một số thứ như
expect(localStorage.getItem).toBeCalledWith('token')
// or
expect(localStorage.getItem.mock.calls.length).toBe(1)
bên trong các bài kiểm tra của bạn nếu bạn muốn chắc chắn rằng nó được gọi. Hãy xem https://facebook.github.io/jest/docs/en/mock-fifts.html
localStorage
bạn sử dụng trong mã của mình. (nếu bạn sử dụng create-react-app
và tất cả các tập lệnh tự động mà nó cung cấp một cách tự nhiên)
expect(localStorage.getItem).toBeCalledWith('token')
hoặc expect(localStorage.getItem.mock.calls.length).toBe(1)
bên trong các bài kiểm tra của bạn nếu bạn muốn đảm bảo rằng nó được gọi. Hãy xem facebook.github.io/jest/docs/en/mock-fifts.html
localStorage
? Bạn có muốn đặt lại các điệp viên sau mỗi bài kiểm tra để ngăn chặn "sự lan tỏa" sang các bài kiểm tra khác không?
Hiện tại (19 tháng 10) localStorage không thể bị chế giễu hoặc theo dõi bởi jest như bạn thường làm, và như được nêu trong các tài liệu ứng dụng tạo phản ứng. Điều này là do những thay đổi được thực hiện trong jsdom. Bạn có thể đọc về nó trong trình theo dõi vấn đề jest và jsdom .
Thay vào đó, bạn có thể theo dõi nguyên mẫu:
// does not work:
jest.spyOn(localStorage, "setItem");
localStorage.setItem = jest.fn();
// works:
jest.spyOn(window.localStorage.__proto__, 'setItem');
window.localStorage.__proto__.setItem = jest.fn();
// assertions as usual:
expect(localStorage.setItem).toHaveBeenCalled();
jest.spyOn(window.localStorage.__proto__, 'setItem');
hoặc bạn chỉ cần lấy một gói giả như thế này:
https://www.npmjs.com/package/jest-localst Storage-mock
nó không chỉ xử lý chức năng lưu trữ mà còn cho phép bạn kiểm tra xem cửa hàng có thực sự được gọi hay không.
Một sự thay thế tốt hơn giúp xử lý undefined
các giá trị (nó không có toString()
) và trả về null
nếu giá trị không tồn tại. Đã thử nghiệm điều này với react
v15 redux
vàredux-auth-wrapper
class LocalStorageMock {
constructor() {
this.store = {}
}
clear() {
this.store = {}
}
getItem(key) {
return this.store[key] || null
}
setItem(key, value) {
this.store[key] = value
}
removeItem(key) {
delete this.store[key]
}
}
global.localStorage = new LocalStorageMock
removeItem
: developer.mozilla.org/en-US/docs/Web/API/Storage/removeItem
Nếu bạn đang tìm kiếm một bản giả và không phải là sơ khai, đây là giải pháp tôi sử dụng:
export const localStorageMock = {
getItem: jest.fn().mockImplementation(key => localStorageItems[key]),
setItem: jest.fn().mockImplementation((key, value) => {
localStorageItems[key] = value;
}),
clear: jest.fn().mockImplementation(() => {
localStorageItems = {};
}),
removeItem: jest.fn().mockImplementation((key) => {
localStorageItems[key] = undefined;
}),
};
export let localStorageItems = {}; // eslint-disable-line import/no-mutable-exports
Tôi xuất các mục lưu trữ để khởi tạo dễ dàng. IE Tôi có thể dễ dàng đặt nó vào một đối tượng
Trong các phiên bản mới hơn của Jest + JSDom, không thể thiết lập điều này, nhưng bộ lưu trữ cục bộ đã có sẵn và bạn có thể theo dõi nó như vậy:
const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem');
Tôi tìm thấy giải pháp này từ github
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
Bạn có thể chèn mã này vào setupTests và nó sẽ hoạt động tốt.
Tôi đã thử nghiệm nó trong một dự án với kiểu chữ.
Thật không may, các giải pháp mà tôi tìm thấy ở đây không hiệu quả với tôi.
Vì vậy, tôi đã xem xét các vấn đề của Jest GitHub và tìm thấy chủ đề này
Các giải pháp được đánh giá cao nhất là những giải pháp sau:
const spy = jest.spyOn(Storage.prototype, 'setItem');
// or
Storage.prototype.getItem = jest.fn(() => 'bla');
window
hoặc Storage
được xác định. Có lẽ đó là phiên bản cũ hơn của Jest tôi đang sử dụng.
Như tài liệu đề xuất @ ck4 có giải thích rõ ràng cho việc sử dụng localStorage
trong jest. Tuy nhiên, các chức năng giả đã không thực hiện bất kỳlocalStorage
phương thức nào.
Dưới đây là ví dụ chi tiết về thành phần phản ứng của tôi, sử dụng các phương thức trừu tượng để ghi và đọc dữ liệu,
//file: storage.js
const key = 'ABC';
export function readFromStore (){
return JSON.parse(localStorage.getItem(key));
}
export function saveToStore (value) {
localStorage.setItem(key, JSON.stringify(value));
}
export default { readFromStore, saveToStore };
Lỗi:
TypeError: _setupLocalStorage2.default.setItem is not a function
Khắc phục:
Thêm chức năng giả bên dưới cho jest (đường dẫn .jest/mocks/setUpStore.js
:)
let mockStorage = {};
module.exports = window.localStorage = {
setItem: (key, val) => Object.assign(mockStorage, {[key]: val}),
getItem: (key) => mockStorage[key],
clear: () => mockStorage = {}
};
Đoạn trích được tham chiếu từ đây
Riff tắt một số câu trả lời khác ở đây để giải quyết nó cho một dự án với Typecript. Tôi đã tạo một LocalStorageMock như thế này:
export class LocalStorageMock {
private store = {}
clear() {
this.store = {}
}
getItem(key: string) {
return this.store[key] || null
}
setItem(key: string, value: string) {
this.store[key] = value
}
removeItem(key: string) {
delete this.store[key]
}
}
Sau đó, tôi đã tạo một lớp LocalStorageWrapper mà tôi sử dụng cho tất cả quyền truy cập vào bộ nhớ cục bộ trong ứng dụng thay vì truy cập trực tiếp vào biến lưu trữ cục bộ toàn cầu. Làm cho nó dễ dàng để đặt giả trong trình bao bọc cho các bài kiểm tra.
describe('getToken', () => {
const Auth = new AuthService();
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ik1yIEpvc2VwaCIsImlkIjoiNWQwYjk1Mzg2NTVhOTQ0ZjA0NjE5ZTA5IiwiZW1haWwiOiJ0cmV2X2pvc0Bob3RtYWlsLmNvbSIsInByb2ZpbGVVc2VybmFtZSI6Ii9tcmpvc2VwaCIsInByb2ZpbGVJbWFnZSI6Ii9Eb3Nlbi10LUdpci1sb29rLWN1dGUtbnVrZWNhdDMxNnMtMzExNzAwNDYtMTI4MC04MDAuanBnIiwiaWF0IjoxNTYyMzE4NDA0LCJleHAiOjE1OTM4NzYwMDR9.YwU15SqHMh1nO51eSa0YsOK-YLlaCx6ijceOKhZfQZc';
beforeEach(() => {
global.localStorage = jest.fn().mockImplementation(() => {
return {
getItem: jest.fn().mockReturnValue(token)
}
});
});
it('should get the token from localStorage', () => {
const result = Auth.getToken();
expect(result).toEqual(token);
});
});
Tạo một bản giả và thêm nó vào global
objectt
Bạn cần mô phỏng bộ nhớ cục bộ bằng đoạn mã này
// localStorage.js
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
Và trong cấu hình jest:
"setupFiles":["localStorage.js"]
Hãy hỏi bất cứ điều gì .
Giải pháp sau đây tương thích để thử nghiệm với TypeScript, ESLint, TSLint và Prettier config { "proseWrap": "always", "semi": false, "singleQuote": true, "trailingComma": "es5" }
:
class LocalStorageMock {
public store: {
[key: string]: string
}
constructor() {
this.store = {}
}
public clear() {
this.store = {}
}
public getItem(key: string) {
return this.store[key] || undefined
}
public setItem(key: string, value: string) {
this.store[key] = value.toString()
}
public removeItem(key: string) {
delete this.store[key]
}
}
/* tslint:disable-next-line:no-any */
;(global as any).localStorage = new LocalStorageMock()
HT / https://stackoverflow.com/a/51583401/101290 để biết cách cập nhật global.localStorage
Để làm tương tự trong Bản đánh máy, hãy làm như sau:
Thiết lập một tệp với các nội dung sau:
let localStorageMock = (function() {
let store = new Map()
return {
getItem(key: string):string {
return store.get(key);
},
setItem: function(key: string, value: string) {
store.set(key, value);
},
clear: function() {
store = new Map();
},
removeItem: function(key: string) {
store.delete(key)
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
Sau đó, bạn thêm dòng sau vào gói.json theo cấu hình Jest của bạn
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
Hoặc bạn nhập tệp này trong trường hợp thử nghiệm của bạn, nơi bạn muốn giả định bộ lưu trữ cục bộ.
value + ''
trong trình thiết lập để xử lý chính xác các giá trị null và không xác định