Existe alguma biblioteca para zombar localStorage
?
Tenho usado o Sinon.JS para a maioria das minhas outras simulações de javascript e descobri que é realmente ótimo.
Meu teste inicial mostra que localStorage se recusa a ser atribuível no firefox (sadface), então provavelmente vou precisar de algum tipo de hack em torno disso: /
Minhas opções a partir de agora (como vejo) são as seguintes:
- Criar funções de empacotamento que todo meu código usa e simular aquelas
- Crie algum tipo de (pode ser complicado) gerenciamento de estado (instantâneo localStorage antes do teste, no instantâneo de restauração de limpeza) para localStorage.
??????
O que você acha dessas abordagens e acha que há outras maneiras melhores de fazer isso? De qualquer forma, colocarei a "biblioteca" resultante que acabo criando no github para as vantagens do código aberto.
javascript
unit-testing
mocking
local-storage
sinon
Anthony Sottile
fonte
fonte
Profit!
Respostas:
Aqui está uma maneira simples de zombar com Jasmine:
Se você quiser simular o armazenamento local em todos os seus testes, declare a
beforeEach()
função mostrada acima no escopo global de seus testes (o local usual é um script specHelper.js ).fonte
ReferenceError: localStorage is not defined
(testes de execução usando FB Jest e npm) ... alguma idéia de como contornar?window.localStorage
andCallFake
alterado paraand.callFake
em jasmim 2. +apenas simule o localStorage / sessionStorage global (eles têm a mesma API) para suas necessidades.
Por exemplo:
E então o que você realmente faz é algo assim:
fonte
getItem
deve retornarnull
quando o valor não existirreturn storage[key] || null;
:;localStorage
como um todo não é possível.storage[key] || null
está incorreto. Sestorage[key] === 0
ele voltará em seunull
lugar. Eu acho que você poderia fazer, noreturn key in storage ? storage[key] : null
entanto.function storageMock() { var storage = {}; return { setItem: function(key, value) { storage[key] = value || ''; }, getItem: function(key) { return key in storage ? storage[key] : null; }, removeItem: function(key) { delete storage[key]; }, get length() { return Object.keys(storage).length; }, key: function(i) { var keys = Object.keys(storage); return keys[i] || null; } }; } window.localStor = storageMock();
TypeError: Cannot set property localStorage of #<Window> which has only a getter
, alguma idéia de como posso corrigir isso?Considere também a opção de injetar dependências na função construtora de um objeto.
Em linha com a simulação e o teste de unidade, gosto de evitar testar a implementação do armazenamento. Por exemplo, não adianta verificar se o comprimento de armazenamento aumentou depois de definir um item, etc.
Visto que obviamente não é confiável substituir métodos no objeto localStorage real, use um mockStorage "burro" e faça stub dos métodos individuais conforme desejado, como:
fonte
Isto é o que eu faço...
fonte
As soluções atuais não funcionarão no Firefox. Isso ocorre porque localStorage é definido pela especificação html como não sendo modificável. No entanto, você pode contornar isso acessando o protótipo de localStorage diretamente.
A solução para vários navegadores é simular os objetos em,
Storage.prototype
por exemploem vez de spyOn (localStorage, 'setItem') use
retirado das respostas de bzbarsky e teogeos aqui https://github.com/jasmine/jasmine/issues/299
fonte
Acabei de escrever um:
Apenas no contexto global. Com uma função de invólucro como acima, funciona perfeitamente.
fonte
var window = { localStorage: ... }
localStorage
, os testes não necessariamente têmlocalStorage
diretamente neles. Esta solução não altera olocalStorage
para outros scripts, portanto, é uma não solução. 1 para o truque do escopoif this.hasOwnProperty(key) return this[key] else return null
Aqui está um exemplo usando sinon spy e mock:
fonte
Substituir a
localStorage
propriedade dowindow
objeto global, conforme sugerido em algumas das respostas, não funcionará na maioria dos mecanismos JS, porque eles declaram alocalStorage
propriedade de dados como não gravável e não configurável.No entanto, descobri que pelo menos com a versão do WebKit do PhantomJS (versão 1.9.8) você poderia usar a API legada
__defineGetter__
para controlar o que acontece selocalStorage
for acessado. Ainda assim, seria interessante se isso funcionasse em outros navegadores também.O benefício dessa abordagem é que você não precisa modificar o código que está prestes a testar.
fonte
Você não precisa passar o objeto de armazenamento para cada método que o utiliza. Em vez disso, você pode usar um parâmetro de configuração para qualquer módulo que toque o adaptador de armazenamento.
Seu módulo antigo
Seu novo módulo com função de configuração de "wrapper"
Quando você usa o módulo no código de teste
A
MockStorage
classe pode ser assimAo usar seu módulo no código de produção, em vez disso, passe o adaptador localStorage real
fonte
export default function
e inicializar um módulo com um argumento como esse é apenas es6. o padrão permanece independentemente.require
para importar um módulo e aplicá-lo a um argumento na mesma expressão. Não há como fazer isso no ES6 que eu conheça. Caso contrário, eu teria usado o ES6import
Decidi reiterar meu comentário à resposta de Pumbaa80 como uma resposta separada para que seja mais fácil reutilizá-la como uma biblioteca.
Peguei o código do Pumbaa80, refinei um pouco, adicionei testes e publiquei como um módulo npm aqui: https://www.npmjs.com/package/mock-local-storage .
Aqui está um código-fonte: https://github.com/letsrock-today/mock-local-storage/blob/master/src/mock-localstorage.js
Alguns testes: https://github.com/letsrock-today/mock-local-storage/blob/master/test/mock-localstorage.js
O módulo cria localStorage e sessionStorage simulados no objeto global (janela ou global, qual deles é definido).
Em meus outros testes de projeto, eu o solicitei com o mocha da seguinte forma:
mocha -r mock-local-storage
para disponibilizar definições globais para todo o código em teste.Basicamente, o código se parece com o seguinte:
Observe que todos os métodos adicionados por meio de
Object.defineProperty
para que não sejam iterados, acessados ou removidos como itens regulares e não contam em comprimento. Também adicionei uma maneira de registrar o retorno de chamada que é chamado quando um item está prestes a ser colocado no objeto. Este retorno de chamada pode ser usado para emular o erro de cota excedida em testes.fonte
Descobri que não precisava zombar disso. Eu poderia alterar o armazenamento local real para o estado que eu queria por meio de
setItem
, em seguida, apenas consultar os valores para ver se ele mudou viagetItem
. Não é tão poderoso quanto zombeteiro, pois você não consegue ver quantas vezes algo foi alterado, mas funcionou para meus propósitos.fonte
Infelizmente, a única maneira de simular o objeto localStorage em um cenário de teste é alterar o código que estamos testando. Você tem que envolver seu código em uma função anônima (o que você deve fazer de qualquer maneira) e usar "injeção de dependência" para passar uma referência ao objeto de janela. Algo como:
Então, dentro do seu teste, você pode especificar:
fonte
É assim que gosto de fazer. Mantém tudo simples.
fonte
créditos para https://medium.com/@armno/til-mocking-localstorage-and-sessionstorage-in-angular-unit-tests-a765abdc9d87 Faça um armazenamento local falso e espie o armazenamento local, quando for calado
E aqui nós usamos
fonte