Junit unit test for default system routines

Asked

Viewed 895 times

2

I have a Java code that checks if there are standard categories registered in the database, if yes it returns true, if he doesn’t return false.

public boolean validaEntradaDeDadosPadrao() {
        System.out.println("Entrei aqui");
        Categoria cat = new Categoria();
        boolean condicao = false;
        List<Categoria> categoria = categoriaDao.listaTodos();
        for (Categoria c : categoria) {
            if (c.getNomeCategoria().equals("Financeiro")) {
                System.out.println("tem categorias cadastradas");
                condicao = false;
            } else {
                System.out.println("nao tem");
                condicao = true;

            }
        }
        return condicao;
    }

My unitary test is like this:

@Test
public void testValidaEntradaDeDadosPadrao() {

    boolean primeiraCompilacaoDoProjeto = false;
    boolean compilacoesEmDiante = true;


    Assert.assertEquals(false, primeiraCompilacaoDoProjeto);
    Assert.assertEquals(true, compilacoesEmDiante);

}

I read and saw that unit tests do not consult at the bank.

I want to know if my test is reasonably good, and what I can improve on to be more consistent.

  • 1

    First, you really need System.out.println()? Me all validation should not send messages. Second: the test does nothing useful and does not test the validation method.

  • Did any of the answers below solve your problem? Do you think you can accept one of them? Check out the [tour] how to do this, if you still don’t know how to do it. This helps the community by identifying the best solution for you. You can only accept one of them, but you can vote for any question or answer you find useful on the entire site.

2 answers

5

Introducing

Tests of any kind need to test something. This example is testing nothing.

You can test whatever you want in the test, you can access database without problems. Of course it is not ideal because tests should ideally run very fast and not have many dependencies.

To make tests meaningful and effective you need a design very good application before anything else. My experience shows that you can only do tests that are worth anything when the programmer can already produce good code. Not that you can’t try, but flawed codes indicate that the programmer hasn’t reached the level of understanding everything that’s needed to produce tests. One of those flaws is not separating responsibilities well. Another is to understand how a language works, how the computer works, the complete understanding of basic mathematics.

So come on.

Your example

Methods should not mix responsibilities. If it is a validator it should not send messages to the user, it is the responsibility of something else, in another class. A validator should only test conditions and say whether it is right or not.

I imagine the method listaTodos() access the database. To facilitate the test you need to have a way to call a method that simulates the result in a controlled way, quickly and without dependencies. One of the ways is to use dependency injection. Another is to completely replace the object class categoriaDao for a version that does not access the database but generates an easily testable result.

There are specific techniques to replace the normal behaviour of a method.

If you choose DI (dependency Injection) is very easy, just receive the object by a parameter. I particularly do not like to change a method just to test, I prefer a more global solution. But it’s an option, so you’d have to rethink all the code of all the classes to be suitable for the test.

Giving an improved in other points the method would look like this:

public boolean validaEntradaDeDadosPadrao() {
    for (Categoria c : categoriaDao.listaTodos()) {
        if (c.getNomeCategoria().equals("Financeiro")) {
            return false;
        }
    }
    return true;
}

I preferred not to change the method name because I do not know the specification of the problem, but it seems wrong.

Then we can do the test (I do not say it is the best way, but a possibility of improvement). I will post here an approximate way:

class Dao {
    public List<Categoria> listaTodos() {
        list<Categoria> lista = new List<>();
        lista.Add(new Categoria("Financeiro")); //claro que é mais complexo que isto
        lista.Add(new Categoria("OutraCategoria"));
        return lista; //nenhum banco de dados é acessado e provê os dados necessários
    }
}

This class would be the substitute for the original that accesses the database. Of course it would be more complex than this.

Here you would have to create infrastructure to test in different ways, provoke different situations, create situation that generates a result or other, that can force an error, make the code run in all possible ways.

@Test
public void testValidaEntradaDeDadosPadrao() {
    Assert.assertEquals(validaEntradaDeDadosPadrao(), true);
}

I put in the Github for future reference.

Here you are testing something useful.

Well, that’s about it. The intention is not to produce the ready-to-use test, because the question data does not allow it, but to give basic information that the test is done differently.

5

The idea of the assertions is to verify if the behavior produced by the method or class equals the expected.

First, System.out.println, as Maniero commented above, it is not necessary, because the idea of automated testing is not to need visual verification by a human being to determine whether they passed or failed (in addition to the final report of successes and failures, of course).

Second, the method name does not match what it does, it says validate data entry, but in practice what it is doing is selecting the categories of a DAO, and checking if there is a "Financial".

Third, Junits can access whatever you want (it’s a free world), but whether or not they should access the database depends on the type of test you want to perform. If what you want is to do Unit Tests, then it is advisable to try to reduce the scope of the test to the maximum, testing only the smallest of the units. In general, for your code, a unit test would use a false implementation of that DAO (which in general does not access a database), which allows the test to inject possible values, or reproduce possible exceptions that are difficult to recreate in a real database.

Fourth, try assertion methods closer to what you are trying to test in the test. For example, assertTrue() and assertFalse() are clearer than assertEquals().

Finally, in general you would write at least two unit tests, one for the assertion being true, and the other for the assertion to be false.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.