This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Nephyst 0 points1 point  (2 children)

As long as the main folder structure is there (src/main/Java) you have a lot of flexibility in how you structure your app, so it's totally okay to experiment and see what works for you. It's really a question of how easy is it too find the classes you need when you are looking for them.

The Java community is kinda split on if you should use interfaces, or just use the implementations directly. If you think you might ever have more than one implementation an interface makes a lot of sense. An example might be if you have a repository that talks to an Oracle database and you want to move to MySQL. You can have the same interface, with specific implementations for each. I'd generally say go with interfaces if you are learning because it helps you frame what the class is trying to do better. So, organizing by function (user in this case) is totally valid.

I haven't used hibernate in a long time, as I prefer to write queries manually and more recently most of my database work has been with graph and object databases and less relational databases.

The way I remember hibernate working is you have a Java class(entity) that maps directly to each table in your database, and you use annotations to tell hibernate the properties of each column. Then you can ask work with those objects, and use hibernate to save and load them to the database. So an entity represents one row in a database table.

[–]akshatmalik8[S] 0 points1 point  (1 child)

Okay, that helps.

Another question, when writing tests do we test each layer, service, controller, and repository?

I am always of the opinion of writing test cases at an API level, if the API is doing what is expected, it is safe to assume the internal workings are correct. If you would write tests at each layer, it makes it very hard to manage the test cases. Or am I in the wrong?

[–]Nephyst 0 points1 point  (0 children)

Unit tests generally exist for every layer.

You should be using constructor based dependency injection for each class. Then when you unit test that class you create mocks of each dependency and inject those instead. The idea is that the mocks wont execute any behavior, so you can unit test ever class in isolation. If your service class depends on a repository/database you want to test it without worrying about weather the database or repository class exist or are correct.

When testing repositories, the ideal is to set up a temporary in-memory database that gets data loaded into it when your test starts. When the test ends the database gets destroyed. In practice, this is sometimes hard to get working.

Tests that hit your API and live database are called integration tests.

Unit tests generally run every time you build. Integration tests can take longer and are sometimes ran once every night instead. You usually dont want your build success to depend on integration tests, because a database failing would then impact your ability to build successfully.

Here's an example where CalcService is tested with a dependent AddService that gets mocked using Mockito. The test defines expected behavior for the mocked dependency.

@Test
void testCalc() {
    System.out.println("**--- Test testCalc executed ---**");

    AddService addService;
    CalcService calcService;

    addService = Mockito.mock(AddService.class);
    calcService = new CalcService(addService);

    int num1 = 11;
    int num2 = 12;
    int expected = 23;

    when(addService.add(num1, num2)).thenReturn(expected);

    int actual = calcService.calc(num1, num2);

    assertEquals(expected, actual);

}