Sunday, September 18, 2016

Abstract: How to write a unit test that is able to instantiate a class using a constructor declared as private. By doing it, cobertura will include the test into its coverage report, helping you to achieve code coverage requirements.

É ponto pacífico que todo código deveria possuir testes unitários. Já para o que precisa ser testado e qual e extensão dos testes, não se tem uma regra clara e sempre gera discussões. Eu em geral busco 100% de cobertura.

Segundo algumas regras de estilo, "esconder" o construtor é uma boa prática e essa prática faz parte do manual de codificação para a empresa em que trabalho. O problema é que o cobertura (sistema que mede o percentual de testes que cobrem um código) não entende isso, e ao analisar o código fonte, acusa que faltam testes para o construtor privado. Com isso, o percentual de cobertura diminui.

Isso não é um problema, na medida em que se você construiu os testes para os métodos estáticos e eles estão funcionando, o construtor também irá funcionar. Mas, eu tenho TOC e depois de dar duro construindo testes, gosto de ver o relatório apontando 100%. Satisfação pessoal. Simples assim.

Então resolvi pesquisar se existiria uma maneira de fazer o cobertura entender que o construtor foi testado e encontrei um jeito legal de se fazer isso. Basta criar um teste unitário conforme exemplificado abaixo. Por reflexão ele irá instanciar a classe usando o método privado, e com isso, satisfazer o cobertura.

@Test
public void testPrivateConstructor() throws Exception {
   Constructor[] constructors = MyUtilityClass.class.getDeclaredConstructors();

// Only the private constructor
assertTrue(constructors.lenght == 1);

// And it should be private

assertFalse(constructors[0].isAccessible());

   constructors[0].setAccessible(true);
   constructors[0].newInstance((Object[])null);
}




Wednesday, September 7, 2016

BTW:

jumble = to move in a confused or disordered manner; to mix into a confused or disordered mass; an untidy collection or pile of things.

Saturday, September 3, 2016

Validação de emails

AbstractJava code that helps into email validation by checking if the domain has a DNS MX record. Into github, I provide a full working app other than the simple code of this post.

Na empresa para qual trabalho estávamos precisando de um validador de emails mais "potente" do que o javascript que verificava o formulário que coletava os emails dos nossos clientes. Ele basicamente validava se o email era bem formado.

Mas como saber se, apesar de bem formado, o email existe?

Antigamente era possível fazer um telnet na porta 25 e descobrir inclusive se o usuário existia. Mas com os spammers, isso acabou sendo bloqueado. Ainda dá para fazer, usando outra abordagem, mas isso é assunto para outro post.

Uma validação simples que pode ser feita é verificar se o domínio do email possui um servidor MX. MX vem de Mail eXchanger e é um registro que fica cadastrado em um DNS. É assim que a "internet" sabe para onde um email tem que ir.

Pesquisando, verifiquei que o java possui um contexto JNDI que nos ajuda com este tipo de tarefa e fica muito fácil fazer a verificação, conforme exemplo abaixo:

public void checkMX(String email) {
   Properties env = new Properties();
   env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");

   String hostname = email.substring(email.indexOf("@") + 1, email.length()).toLowerCase().trim();

   try {
      InitialDirContext idc = new InitialDirContext(env);
      Attributes attributes = idc.getAttributes(hostname, new String[] { "MX" });
      Attribute attribute = attributes.get("MX");
      System.out.println(attribute);
   } catch (NamingException e) {
      e.printStackTrace();
   }
}

Se você chamar o método e passar um email do gmail, ele vai imprimir na console "MX: 5 gmail-smtp-in.l.google.com., 40 alt4.gmail-smtp-in.l.google.com., 10 alt1.gmail-smtp-in.l.google.com., 20 alt2.gmail-smtp-in.l.google.com., 30 alt3.gmail-smtp-in.l.google.com.".

Os números na frente dos servidores indica a prioridade. Quanto menor, mais importante. No exemplo acima, primeiro o email tentará ser entregue ao servidor com prioridade 5, depois 10 e assim por diante.

Na minha conta do github eu coloquei uma aplicação um pouco mais completa, que lê um arquivo texto com uma lista de emails e gera um log de processamento com o resultado das validações.

Espero que seja útil.