Eu quero executar um pequeno banco de dados PostgreSQL que é executado apenas na memória, para cada teste de unidade que escrevo. Por exemplo:
@Before
void setUp() {
String port = runPostgresOnRandomPort();
connectTo("postgres://localhost:"+port+"/in_memory_db");
// ...
}
Idealmente, terei um único executável do postgres verificado no controle de versão, que o teste de unidade usará.
Algo assim HSQL
, mas para postgres. Como eu posso fazer isso?
Onde posso obter essa versão do Postgres? Como posso instruí-lo a não usar o disco?
testcontainers
, que essencialmente permite que seu teste inicie uma instância postgres descartável, dockerizada. Consulte github.com/testcontainers/testcontainers-java/blob/master/…(Movendo minha resposta do Uso do PostgreSQL na memória e generalizando-o):
Você não pode executar o Pg em processo, na memória
Não, não é possível. PostgreSQL é implementado em C e compilado para o código da plataforma. Ao contrário do H2 ou Derby, você não pode simplesmente carregar o
jar
e ativá-lo como um banco de dados in-memory descartável.Ao contrário do SQLite, que também é escrito em C e compilado para o código da plataforma, o PostgreSQL também não pode ser carregado durante o processo. Requer vários processos (um por conexão) porque é uma arquitetura de multiprocessamento, não multithreading. O requisito de multiprocessamento significa que você deve iniciar o postmaster como um processo independente.
Em vez disso: pré-configure uma conexão
Eu sugiro simplesmente escrever seus testes para esperar que um determinado nome de host / nome de usuário / senha funcione, e ter o teste de controle de
CREATE DATABASE
um banco de dados descartável, entãoDROP DATABASE
no final da execução. Obtenha os detalhes de conexão do banco de dados de um arquivo de propriedades, crie propriedades de destino, variável de ambiente, etc.É seguro usar uma instância existente do PostgreSQL na qual você já tenha bancos de dados importantes, contanto que o usuário fornecido para os testes de unidade não seja um superusuário, apenas um usuário com
CREATEDB
direitos. Na pior das hipóteses, você criará problemas de desempenho em outros bancos de dados. Eu prefiro executar uma instalação do PostgreSQL completamente isolada para teste por esse motivo.Em vez disso: inicie uma instância descartável do PostgreSQL para teste
Alternativamente, se você estiver realmente interessado, pode fazer com que seu equipamento de teste localize os binários
initdb
epostgres
, executeinitdb
para criar um banco de dados, modifiquepg_hba.conf
paratrust
, executepostgres
para iniciá-lo em uma porta aleatória, crie um usuário, crie um banco de dados e execute os testes . Você pode até empacotar os binários do PostgreSQL para múltiplas arquiteturas em um jar e descompactar os da arquitetura atual em um diretório temporário antes de executar os testes.Pessoalmente, acho que é uma grande dor que deve ser evitada; é muito mais fácil apenas ter um banco de dados de teste configurado. No entanto, ficou um pouco mais fácil com o advento do
include_dir
suporte empostgresql.conf
; agora você pode apenas anexar uma linha e escrever um arquivo de configuração gerado para todo o resto.Teste mais rápido com PostgreSQL
Para obter mais informações sobre como melhorar com segurança o desempenho do PostgreSQL para fins de teste, consulte uma resposta detalhada que escrevi sobre este tópico: Otimize o PostgreSQL para testes rápidos
O dialeto PostgreSQL de H2 não é um verdadeiro substituto
Algumas pessoas, em vez disso, usam o banco de dados H2 no modo de dialeto PostgreSQL para executar testes. Eu acho que isso é quase tão ruim quanto o pessoal do Rails usando SQLite para testes e PostgreSQL para implantação de produção.
H2 suporta algumas extensões PostgreSQL e emula o dialeto PostgreSQL. No entanto, é apenas isso - uma emulação. Você vai encontrar áreas onde H2 aceita uma consulta, mas PostgreSQL não faz, onde difere de comportamento, etc . Você também encontrará muitos lugares onde o PostgreSQL suporta fazer algo que o H2 simplesmente não consegue - como funções de janela, no momento da escrita.
Se você entender as limitações dessa abordagem e seu acesso ao banco de dados for simples, H2 pode ser adequado. Mas, nesse caso, você provavelmente é um candidato melhor para um ORM que abstrai o banco de dados porque você não está usando seus recursos interessantes de qualquer maneira - e, nesse caso, você não precisa mais se preocupar tanto com a compatibilidade do banco de dados.
Os espaços de tabela não são a resposta!
Você não usar uma tabela para criar um banco de dados "in-memory". Além de desnecessário, não ajudará no desempenho de maneira significativa, mas também é uma ótima maneira de interromper o acesso a qualquer outro que seja do seu interesse na mesma instalação do PostgreSQL. A documentação 9.4 agora contém o seguinte aviso :
porque percebi que muitas pessoas estavam fazendo isso e tendo problemas.
(Se você fez isso, pode
mkdir
remover o diretório do espaço de tabela ausente para fazer o PostgreSQL iniciar novamente, depoisDROP
os bancos de dados, tabelas etc. ausentes. É melhor simplesmente não fazer isso.)fonte
initdb
instalar uma nova Pg lá. Mas, realmente, há pouca diferença entre um Pg que é ajustado para testes rápidos em armazenamento normal (fsync = off e outros recursos de durabilidade / segurança de dados desativados) do que rodar em um ramdisk, pelo menos no Linux.Ou você pode criar um TABLESPACE em um ramfs / tempfs e criar todos os seus objetos lá.
Recentemente, fui apontado para um artigo sobre fazer exatamente isso no Linux .
Aviso
Isso pode colocar em risco a integridade de todo o cluster de banco de dados .
Leia o aviso adicionado no manual.
Portanto, esta é apenas uma opção para dados dispensáveis.
Para o teste de unidade , deve funcionar bem. Se você estiver executando outros bancos de dados na mesma máquina, certifique-se de usar um cluster de banco de dados separado (que tem sua própria porta) para segurança.
fonte
initdb
uma nova instância do postgres em um tempfs ou ramdisk. Você não usar uma tabela em um tempfs etc, é frágil e inútil. É melhor usar um espaço de tabela normal e criarUNLOGGED
tabelas - o desempenho será semelhante. E não tratará do desempenho do WAL e dos fatores fsync, a menos que você execute ações que arriscarão a integridade de todo o banco de dados (consulte stackoverflow.com/q/9407442/398670 ). Não faça isso.Agora é possível executar uma instância na memória do PostgreSQL em seus testes JUnit por meio do componente PostgreSQL incorporado do OpenTable: https://github.com/opentable/otj-pg-embedded .
Adicionando a dependência à biblioteca otj-pg-embedded ( https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded ) você pode iniciar e parar sua própria instância do PostgreSQL em seu @Before e @Afer hooks:
Eles até oferecem uma regra JUnit para que o JUnit inicie e pare automaticamente o servidor de banco de dados PostgreSQL para você:
fonte
@Rule
por@ExtendWith
? Basta usar o.start()
em@BeforeAll
?DataSource embeddedPostgresDS = EmbeddedPostgres.builder().start().getPostgresDatabase();
Você pode usar TestContainers para ativar um contêiner docker PosgreSQL para testes: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/
TestContainers fornecem um JUnit @ Rule / @ ClassRule : este modo inicia um banco de dados dentro de um contêiner antes de seus testes e o desmonta depois.
Exemplo:
fonte
Agora existe uma versão na memória do PostgreSQL da empresa Russian Search chamada Yandex: https://github.com/yandex-qatools/postgresql-embedded
É baseado no processo de incorporação do Flapdoodle OSS.
Exemplo de uso (da página do github):
Estou usando há algum tempo. Isso funciona bem.
ATUALIZADO : este projeto não está mais sendo mantido ativamente
fonte
Você também pode usar as definições de configuração do PostgreSQL (como as detalhadas na pergunta e resposta aceita aqui ) para obter desempenho sem necessariamente recorrer a um banco de dados na memória.
fonte
Se estiver usando NodeJS, você pode usar o pg-mem (isenção de responsabilidade: eu sou o autor) para emular os recursos mais comuns de um banco de dados postgres.
Você terá um banco de dados completo em memória, isolado e independente de plataforma, que replica o comportamento do PG (ele até roda em navegadores ).
Eu escrevi um artigo para mostrar como usá-lo para seus testes de unidade aqui .
fonte