J
J
joha07382021-11-06 14:07:49
Spring
joha0738, 2021-11-06 14:07:49

How should a test for a simple Java application look like?

Good day, I am new to JAVA programming and have never encountered testing.
I want to ask you to help with writing tests for simple web application methods (JAVA, SPRING, H2). I just have an application with 2 entities (Planets (Name), Rulers (Name, Age)) and a list of functionality for which I need to write tests:
- Add a new Overlord
- Add a new Planet
- Assign an Overlord to rule a Planet
- Destroy a Planet
- Find all the Overlords of idlers who are chilling and do not rule any Planets
- Display the TOP 10 youngest Overlords.

@Controller
public class MainController {

    @Autowired
    private LordsRepository lordsRepository;

    @Autowired
    private PlanetsRepository planetsRepository;
 
@PostMapping("/createLord")
    public String postCreateLord(@RequestParam(value = "name") String name,@RequestParam(value = "age") int age){
        Lords lord = new Lords();
        lord.setName(name);
        lord.setAge(age);
        lordsRepository.save(lord);
        return "redirect:/";
    }

 @PostMapping("/createPlanet")
    public String postCreatePlanet(@RequestParam(value = "name") String name){
        Planets planet = new Planets();
        planet.setName(name);
        if(planetsRepository.findByName(name) == null)
        planetsRepository.save(planet);
        return "redirect:/planets";
    }

@GetMapping("/destroy/{id}")
    public String destroyPlanet(@PathVariable(value = "id") Planets planet){
        planetsRepository.delete(planet);
        return "redirect:/planets";
    }

@GetMapping("/newPlanetLord/{planet.id}/{lord.id}")
    public String newPlanetLord(@PathVariable(value = "planet.id") Planets planet,@PathVariable(value = "lord.id") Lords lord){
        planet.setLord(lord);
        planetsRepository.save(planet);
        return "redirect:/planets";
    }

@GetMapping("/young")
    public String youngLord(Model model){
        List<Lords> lords = lordsRepository.findAll();
        lords.sort(Comparator.comparingInt(x->x.getAge()));
        model.addAttribute("lords",lords.stream().limit(10).toList());
        return "young";
    }

    @GetMapping("/withoutPl")
    public String withoutLord(Model model){
        List<Lords> lords = lordsRepository.findAll();
        List<Lords> lords1 = new ArrayList<>();
        lords.stream().filter(x->x.getPlanets().size()==0).forEach(x->lords1.add(x));
        model.addAttribute("lords",lords1);
        return "withoutPlanet";
    }


I tried to find at least some guides for writing tests, but all the guides boiled down to the fact that the author posted already written code without a sensible explanation of "what is what and why".

Here is the test code I wrote, after running it does not give me errors, but it seems to me that I wrote some kind of nonsense .....

@SpringBootTest
public class PlanerAppApplicationTests {

    @Mock
    private MainController mainController;

    @Autowired
    private LordsRepository lordsRepository;

    @Autowired
    private PlanetsRepository planetsRepository;

    @Test
    public void createLord(){
        mainController.postCreateLord("John",23);
        mainController.postCreateLord("John2",20);
    }

    @Test
    public void createPlanet(){
        mainController.postCreatePlanet("saturn");
        mainController.postCreatePlanet("saturn2");
    }

    @Test
    public void destroyPlanet(){
        Planets planet = planetsRepository.getById(3l);
        mainController.destroyPlanet(planet);
    }

    @Test
    public void setLordOnPlanet() {
        Lords lord = lordsRepository.getById(1l);
        Planets planet = planetsRepository.getById(1l);
        mainController.newPlanetLord(planet,lord);
    }

    @Test
    public void tenYoungLord(){
        List<Lords> lords = lordsRepository.findAll();
        lords.sort(Comparator.comparingInt(x->x.getAge()));
    }


    @Test
    public void lordWOPlanet(){
        List<Lords> lords = lordsRepository.findAll();
        List<Lords> lords1 = new ArrayList<>();
        lords.stream().filter(x->x.getPlanets().size()==0).forEach(x->lords1.add(x));
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
rPman, 2021-11-06
@joha0738

When you develop some kind of application, no matter how complex, you don’t write it from scratch to the end completely (more precisely, this happens but rarely, for not very large tasks and this method has drawbacks - it is more prone to errors), on the contrary, the code is ideologically divided into parts or development stages, each of which is written in turn, until the fundamental possibility of launching, often by the way, stubs are substituted into the already written parts (and / or the database is slipped in a certain state ) and debug messages are added so that the application starts in the desired state that in principle it was possible to test the part just written.
By test, I mean any way to check what happens, how the program reacts (for example, what it writes in the logs), and compare it with the expected behavior.
What is expected behavior? when you divide a task into subtasks, you get intermediate data and states, like in a joke about a teapot and a programmer, to make tea you need to:
* pour water into the teapot
* put it on the base / stove and turn it on
* wait for it to be ready / turn it off
* pour tea
at each stage, you need to check the status, for example, the first item is whether there is water in the kettle, whether it is hot or cold, whether the kettle is full, whether you have a kettle in your hands, etc.
Tests are created on the basis of data that is normal, abnormal and boundary for those algorithms that are used in the code. For example, there is no need to check the temperature of the water in the kettle separately for fixed values ​​​​of 10, 20, 30, .. degrees, if their natural boundaries are laid in the algorithm - cold and hot, and you have to walk around these constants.
It is precisely these checks that are the tests that need to be automated.
The degree of completeness of testing is a philosophical question, ultimately, tests are needed not only for automatic testing and reporting on code changes, but also for development itself, by developing tests you make the code more complete and accurate (for example, by checking the temperature of the water in the first step, you will add a condition to the code - if the water is hot, then skip heating it), read about test-driven development, TDD
ps and also tests are a way to explore an unknown library, the fact is that open source realities are such that there is no documentation from the word at all, at best you have a list of methods with argument types and a couple of examples, everything else needs to be guessed from the logic of names, common sense meaning and picking in the source code. The tests here can be solely as a way to study this library, but it is not necessary to implement such tests in code, it is still a manual process, but nevertheless, creating tests for answers from someone else's library is useful for long-term support of the project so that you there were alerts about her unusual behavior after the update)
creating correct and complete tests greatly increases the cost of developing and maintaining the project, and almost by an order of magnitude, but gives some protection against the death of the project in the future due to accumulating errors, about which nothing is clear without tests.
and yet, creating tests from scratch for a finished project is almost impossible.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question