Go Fakedb Emulação de banco de dados em testes

Outro dia escrevi testes para um módulo que interage com um banco de dados. Eu não queria vincular o módulo de teste a esse banco de dados - isso cria requisitos adicionais para o ambiente em que o teste será realizado. Eu também não queria criar instâncias do tipo sql.Rows com as chapas necessárias de uma só vez - para mim esse tipo é uma "caixa preta" e gostaria que permanecesse dessa maneira. A pesquisa no tópico também não encontrou nada de interessante.


Eu queria compartilhar minha descoberta com a comunidade: na distribuição principal do Go, existe uma ferramenta quase pronta para essas necessidades: chamada FakeDb.


O que essa ferramenta pode fazer?


Na verdade, é o objeto de banco de dados mais simples, mas completo, um banco de dados que pode criar tabelas, preenchê-las e fazer amostras simples a partir delas. Todas as tabelas criadas são temporárias e existem enquanto existir a instância FakeDb. Além disso, a emulação de atraso ao chamar um comando e a exceção de emulação estão disponíveis.


Comandos do FakeDb


Os comandos consistem em frases separadas por uma barra vertical - |. Uma frase é uma palavra-chave ou uma expressão no formato "chave = valor". Onde chave é o nome da coluna.


Limpe
O comando destrói as tabelas e retorna um resultado vazio. Além disso, verifica-se que não há conflito.
Exemplo de chamada:
WIPE


CRIAR
O comando cria uma tabela com as colunas especificadas do tipo especificado.


Formato da chamada:


CREATE|_|1=,...,N=


Tipos suportados:


  • bool
  • nullbool - booleano ou nulo
  • int32
  • corda
  • nullstring - string ou NULL
  • int64
  • nullint64 - int64 ou NULL
  • float64
  • nullfloat64 - float64 ou NULL
  • data e hora
  • any - interface vazia, ou seja, qualquer tipo

Exemplo de chamada:


CREATE|people|name=string,age=int32,photo=any,dead=bool,bdate=datetime


INSERIR
O comando adiciona linhas à tabela criada.


Formato da chamada:
INSERT|_|1=,...,N
A seguir, o valor pode ser definido de três maneiras:


  1. Especifique explicitamente um valor, por exemplo 123 .
  2. Indique "?" E passe o valor como parâmetro.
  3. Especifique "? Parameter_name" e passe o valor para o parâmetro nomeado.

Exemplo de chamada:


INSERT|people|name=Alice,age=?,photo=?photo


SELECT
O comando permite selecionar todas as linhas da tabela ou com alguma seleção.
Formato da chamada:


 SELECT|_|1,...,N| SELECT|_|1,...,N|1=?,...,M 

Exemplo de chamada:


 SELECT|categories|category_id,category_parent_id,category_name| SELECT|categories|category_id,category_parent_id,category_name|category_parent_id=?parent 

O resultado é uma instância completa do sql.Rows.


WAIT
Simula um atraso na execução de um comando. Deve ser adicionado antes de qualquer um dos comandos acima.
Formato da chamada:
WAIT||


O atraso é indicado como a quantidade e o postfix que indicam a unidade de medida: s - segundos, n - nanossegundos, u - microssegundos, h - horas e assim por diante (a função time.ParseDuration () é usada).


Exemplo de chamada:
WAIT|1s|SELECT|categories|category_id,category_parent_id,category_name|


Pânico
Lança uma exceção ao chamar um comando.
Formato da chamada:
PANIC|_|


O valor de MethodName será colocado no campo stmt.panic (digite fakeStmt).


Exemplo de chamada:
PANIC|blablabla|SELECT|categories|category_id,category_parent_id,category_name|


Use


O FakeDb foi criado para testar o pacote "sql" da entrega principal como um script de teste . Não o encontrei em um pacote separado. Portanto, eu mesmo o selecionei em um pacote e o coloquei aqui: gihub .


Foram necessárias edições menores para destacar o pacote.


Exemplo de uso


 package packname import ( "fmt" "testing" "io/ioutil" "database/sql" "github.com/a1div0/fakedb" ) func TestFoo(t *testing.T) { fc := &fakedb.FakeConnector{ } db := sql.OpenDB(fc) if db.Driver() != fakedb.Fdriver { t.Error("OpenDB should return the driver of the Connector") return } if _, err := db.Exec("WIPE"); err != nil { t.Error("exec wipe: %v", err) } defer db.Close() db.Exec("CREATE|users|user_email=string,user_id=int64") db.Exec("INSERT|users|user_email=?,user_id=?", "test@email.com", 345) rows, err := db.Query( "SELECT|users|user_id|user_email=?email", sql.Named("email", user_email), ) if err != nil { t.Error(err) } result, err := Foo(rows) //   if err != nil { t.Error(err) } if result != 123 { t.Error(" ,   Foo()   ;)") } } 

Obrigado pela atenção.


PS: Por favor, escreva nos comentários - você usa emulação de banco de dados nos testes? Em caso afirmativo, qual pacote?

Source: https://habr.com/ru/post/pt485280/


All Articles