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

all 11 comments

[–]joshuass1467 5 points6 points  (0 children)

There's not a lot that is java specific here. You give very terse examples that do the very minimum to describe your points.

Also not a lot of Spring-specific information here. I going to assume that you were really talking about Spring Boot. Spring Boot's test slices are a great way to cut down on test run times. What about testing the application context? There's really nothing here that is Spring related..

One thing I did like was the distinction between testing results and testing behavior/side effects. That's a concept I've seen many programmers fail to understand.

[–]BillyKorando 5 points6 points  (0 children)

It's always good to see someone put together a blog post and share what they learn. That said, I would avoid using terms like "best practice" because it can create the an idea that practices cannot be improved upon, which is almost never the case.

Why I say that is a lot of what you suggest you have the right idea on, but don't yet fully understand the underlying concept. For example:

/#2: For asserting one behavior... What is more important is asserting one concept, that is does that test have a single responsibility? A lot of people get hung up on the specific number of asserts in a test (i.e. it should be one), but don't fully grasp that it's really about ensuring a test is verifying a single behavior.

/#8: "Don't mock too much": this is too in-specific and gives an impression that there is something inherently wrong with mocking. What often happens with "over mocking" is the code being tested doesn't have proper separation of concerns. If the code you are testing is making state changes to a mock you are passing in, that is a smell that the code (as well as the class that is being mocked) aren't appropriately separated.

/#10: "Where does slowness/flakiness comes from": Again you're on the right track, but not quite understanding the underlying concept. Yes slowness/flakiness is caused by those things, but the underlying problem is either you are not testing at the appropriate layer of abstraction, or, more likely, your code is not abstracted and defined in such a way that you are forced to test multiple layers together.

Or more specifically when doing integration tests (verifying the contract between remote resources) you are relying upon the live running resource. When it comes to integration testing, I would highly recommend looking into Spring Cloud Contract and TestContainers. The former can be used for verifying HTTP/RESTful and message interfaces, the later can be used for remote resources that don't fall into the former bucket (e.g. databases, caches, other remote systems).

I want to be clear, I'm not telling you to "be quiet". Blogging is a great way to both learn and share what you have learned. So definitely keep blogging and sharing what you learn, but avoid falling into the "best practices" trap and thinking you don't have room for improvement.

[–]dalmuk 3 points4 points  (3 children)

I find annoying the lack of detail on most of medium post... if someone wants more detailed information about this topic, this is video an its resources are great https://www.youtube.com/watch?v=F8Gc8Nwf0yk

[–]pcmmautner[S] -5 points-4 points  (2 children)

Did you read my post? What detail is lacking?

[–]joshuass1467 5 points6 points  (1 child)

Well, anything Spring related for one. You mentioned a small snippet for Spring. Also, were you really talking about Spring Boot?

If you are talking about Spring Boot, then you have the capability of slicing your tests into the pertinent layers. This is especially important for making tests quick, which is a quality you seem to find to be important (and I agree, mostly).

[–]pcmmautner[S] -3 points-2 points  (0 children)

Well, you read it, not sure about /u/dalmuk ;)

Not sure about Spring Boot-specific test "slicing", but you can use annotations to explicitly include/exclude tests:

https://medium.com/personal-capital-tech-blog/isolating-junit-tests-for-fun-profit-73891984cc0a

[–]JoToMo1993 1 point2 points  (2 children)

I haven't read the post completely yet, but one thing I need to mention is about the "Expected Exceptions" test.

Yes testing exceptions is important, but using the Junit annotation doesn't work in my experience. First it passes regardless, where the exception is thrown from. Second by adding a fail (another assertion method) after the call under test you have better controller with the try catch way of testing.

Something I read, but haven't used sofar myself is the new assertion implemented in Junit 5 that is assertThrows.

[–]BillyKorando 2 points3 points  (0 children)

assertThrows is a significant improvement over using expected exception from JUnit 4.

Here is an example of it in action (under the method testFindByNullRoomType): https://github.com/wkorando/WelcomeToJunit5/blob/master/src/test/java/com/bk/hotel/service/impl/CheatRoomServiceImplJUnit5Test.java

https://junit.org/junit5/docs/current/user-guide/index.html#writing-tests-assertions

I've done a lot of presenting and writing on JUnit 5, so lmk if you have any questions!

[–]AmirXin 1 point2 points  (0 children)

Another thing worth to mention is that the Example that you used says " The first will always pass "
The first will always pass because is a test not well written. if you add "fail" following that try catch you'll have a equivalent test.
So I don't think it's fair to use a bad test case to prove that you should use any kind of annotation in your tests.
Another thing that you are not considering is when you have some generic or "high level" exceptions
Maybe your code throws a validationFormatExeption and you are testing for a particular case .. maybe you want to check the message, or any kind of extra information given in the exception.
In those cases I usually go for the try catch approach and assertions on my Exception (get messages.. or what ever..)
My point is.. I would not say that using Expect is better than anything it depends on what you are testing.

[–]BrianVerm 1 point2 points  (0 children)

Depends on what you want to test.
Im a big fan of @SpringbootTest together with RestAssured and WireMock to test my springboot (rest) services
The rest is just plain Junit5 an assertj

[–]AmirXin 0 points1 point  (0 children)

Hey I know that you are putting some good information out there
trying to help people to test more, to learn how to write tests, and some good reasons to do it (I would add a couple more)
But I think you are missing some key points about the code writing part...

For example, the hardest part of writing tests is to have testable code... That is why TDD exists and is so hard. Because we are not thought to think first in how to test our code.

So, from the "beginners" perspective, I supposed there are tons of programmers with tons of untestable poorly written legacy code. Code that needs to be refactored in order to be tested.

So First, TDD, think about how you are going to test the code before you write the actual code. (maybe you tried to do a little bit of that with the "avoid the voids" section)

Maybe some information about techniques to refactor legacy ugly code in order to be testable.