Testing in Java - Fundamentals
First of all, this article is the beginning of a series which fundamental testing strategies and contains lots of java testing topics.
What are the unit and unit testing?
Firstly, we need to describe unit keyword. Unit is the smallest structure in software, it is also called function/method, all of this production code contains the business logic.
Why should we write unit test?
1. Feel free to add the new feature or refactor
You can be beware to add a new feature or refactor when working on any complex domain that contains several long methods.
if I affected the running of existing code?
This worry can bother us and it can be needed to review all methods, this situation may take us a long time. Whereas we can feel free if we had written unit test and a hundred percentage branch coverage. You can see what is the coverage in the last section of this post.
2. Rapid feedback to production code as quickly as possible
Release Frequency is the most important process in modern software development strategies. Therefore, you need to notice earlier working or not by getting feedback about your code. That’s a very important situation getting feedback quickly or earlier for release the code. Imagine you’re working together with somebody on any issue. Your colleague can be noticed or giving feedback about the code. This situation is the first step to take feedback.
On the other hand, the second step is the unit test. Unit tests run quickly (about minutes) and give feedback about working or not of your code.
3. Improve your code quality
Writing unit test provides thinking about the production code which means that’s an opportunity to apply rules of code smell.
Unit tests protect the production code
That’s a very important sentence above. You can see in detail the following before we detail started you have to know the mock.
What is a mock object?
You can think of it as a simulate a real object. For instance, you can use mock objects to simulate behaviors of the dependencies of the class to be tested. In this way, you can test the classes independently.
Let’s take a look at the image which user action scenario following. Imagine, a user wants to update address information correctly that saved before and than sending a notification like your address has been updated. I think this use case suitable the beginners in unit test as well.
Constructor Injection may have caught your attention at the first looking. There is some injection type that can be applying in java as in many object-oriented programming languages. The biggest advantage to applying constructor injection is avoid the circular dependency.
You should review twice your code if has a circular dependency, most probably you’re able to redesign your code.
RunWith: Specifies in which context the test class is running, an other word there are usable lots of custom runners which extended Runner.java. In this case we use mockito and apply mockito runner. The main goal of any custom runner is manage test execution lifecycle.
Captor: Helps to get argument data that couldn’t access directly of invoked any mock method. For instance, we can use to get data that creates inside the method and passed to any method as a parameter.
Before: You’re able to want to create common data when before each running test method. In other words, before scope can be used to instantiate a new class and passing the parameters that mocked services as you can see above code piece.
Test annotation to the beginning of junit to indicate that method is a test method, each test method should be public and void method. We used the builder pattern in test method, because easy to read when we look at the first time.
When: If there is a dependency injected where your method, indicates what to do when calling the method used by your code.
Verify: We use this to make sure that another dependency method is called. This method quite important to write to test method in a quality way as well.
Assert: Assertion statements produce output about the unit test. It can be used to equal or not two objects or collections. we used assertTrue above test example for end-user should see worst seller center screen.
I think it is more accurate to use assert expressions in the jupiter api instead of junit package. Because jupiter api gives more information about any error and quite understandable messages. Let’s see difference about this like bellow images.
Expect: In some cases, you can be needed to throw an exception when couldn’t perform the mission of any logical situation. Also, in our case, you can see throwing an custom exception when it couldn’t update the member address.
One of the most important things is naming in testing. There are different conventions on this subject. I need to tell that the method names should be a readable because they save lots of time when your teammates understand what you test in that method at first sight.
Naming does matter for unit tests.
Declaretive Statements: Test names which are written as clearly as possible are present to easy to maintainable circumstances. Unit tests are also documentation of written code at the same time. Taking a long time deciding the right test name shouldn’t think as a loss of time. This situation can be thought a loss of time in the short term but it saves more time for teammates in the long term.
I’d like to share the last a stuff about this topic. You shouldn’t assume your code working whatever, the guaranteed way to learn your code working or not, writing the unit test.
The assumption is the biggest evil
I thought that to proper until this section for fundamental unit testing topics. You can review in detail which shared code pieces of this article in github project. I’m thinking to mention coverage and other deep topics need to write quality test code in the next article.
You can feel free to leave your comment or positive/negative feedback 👇