DEV Community

Cover image for My first ever unit test
Bassem
Bassem

Posted on

My first ever unit test

I consider myself quite late. Being in the second year of my career and my first ever unit test was a few days ago. Lately, I joined the backend team and they have a test coverage policy. Because of this policy, every developer working on a certain task have to do the unit tests to cover his/her task. I have always liked the idea of having tests acting as a friend that increases your confidence in your work and help you identify bugs 🐞 quickly making your work easier and better. Anyway, my first task in the backend team was to expose a simple GET URL. We are using spring as a development framework, Mockito as the mocking framework and JUnit for testing.
In this post, I would like to share with you my first ever test.

What is unit testing? 🤔

According to Wikipedia, It is “a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use”

In order to unit test your application, you have to follow the design principle of having small unit modules that you can test. If you are going to test a small component of your application. it needs to be isolated from all other components. That's where Mockito comes in. That’s where you will have to mock and abstract any external dependencies.
The way I see it is that unit testing follows the divide and conquer methodology :

  1. Isolate your code by mocking external dependencies
  2. Think about every possible scenario
  3. Write your tests for this particular unit covering every scenario
  4. Do this until every unit in your application is tested

My super simple yet super awesome task. 😎

Being my first task ever in spring. I choose the simplest one I could get. The code below is a controller that retrieves a resource from the service layer and based on the response, The controller would respond with a 200 or a 404 response code.

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<Resource>> getAllResource() {
    List<Resource> resourceList = resourceService.getAllResource();

    if (resourceList.size() > 0) {
        return new ResponseEntity<List<Resource>>(resourceList, null, HttpStatus.OK);
    }
    return new ResponseEntity<List<Resource>>(null, null, HttpStatus.NOT_FOUND);
}

Very simple, Isn't it? If you think about it, All the logic in the code above boils down to an IF condition. And that's exactly what we are gonna test.

Let's write tests for that awesome task. 😎

Okay, let's follow the above steps :

  1. Isolate: In that case, we need to isolate the controller by mocking the call to the service layer. This way we divide the cycle into units and then test every unit independently. In this post, I am only testing the controller unit.
  2. Cover every scenario: In that case we have 2, Either we have something to return or we don’t. If the list of the resource returned by the mocked service layer is not empty then the output should be a 200. If not then the output should be a 404.
  3. Writing the tests covering each scenario:

Either the service layer returned a non-empty list, The controller then would return a 200 status code

@Test
public void testGetAllResourceSuccess() {
    List<Resource> resourceList = new ArrayList<Resource>();
    resourceList.add(new Resource());

    // Here we mock the service layer function and set the response to a non-empty list.
    Mockito.when(resourceServiceImpl.getAllResource()).thenReturn(resourceList);
    try {
        // Then we expect the response to be a 200
        mockMvc.perform(get(/resource")).andExpect(status().isOk());
    } catch (Exception e) {}
}

Or the service layer returned an empty list, The controller then would return a 404 status code

@Test
public void testGetAllResourceFail() {
    List<Resource> resourceList = new ArrayList<Resource>();
    // Here we mock the service layer function and set the response to an empty list.
    Mockito.when(resourceServiceImpl.getAllResource()).thenReturn(resourceList);
    try {
        // Then we expect the response to be a 404
        mockMvc.perform(get("/resource")).andExpect(status().isNotFound());
    } catch (Exception e) {}
}

Looks easy, simple and straightforward, Isn't it? Well, that’s how unit tests are.
At first, I felt like that can't be it. I felt that this was too simple, that I will never actually fail. Then after some researching, everything made sense. You don’t actually have to test the whole cycle in one test case. In every test case, you cover a small unit. Doing this everywhere means that every bit on its own is working correctly. That's why it's really important to cover every unit in your project.

Happy coding 🔥🔥

Top comments (18)

Collapse
 
alfanse profile image
Alex

Please consider removing the try catch from your example. It risks a false positive test result.

You may simply have the test method signature throw Exception.

Collapse
 
bassemibrahim profile image
Bassem

Will definitely consider that thanks.

Collapse
 
cathodion profile image
Dustin King

I was going to say this too. I'm not familiar with Mockito, but test frameworks I've used in the past use exceptions to signal to the test runner when the assertion fails.

Collapse
 
recursivefaults profile image
Ryan Latta

Hooray for testing!

As time goes on you'll begin to uncover that writing tests is a whole different skillset. Enjoy getting better at it!

As you continue to test, here are a few experiments to consider:

1) Mocking - Used to isolate pieces of code from one another. How would you write this test without mocking? What would the smallest, "Unit" of code that you can test be? What might that tell you about your coupling?

2) Write your test first. Write a test that expresses the wish of your code. Watch it fail, then work to get it to pass. How does your test/implementation code look compared to the other way?

Collapse
 
bassemibrahim profile image
Bassem

yeah, I read about the test-driven approach, Sounds cool. But I don't feel that many people are using it

Collapse
 
borgerstoon profile image
Toon Borgers

Another (Spring specific tip): ResponseEntity has helper factory methods to get a response for a specific status. See here for some examples (starting from Furthermore, ResponseEntity provides two nested builder interfaces)

Collapse
 
bassemibrahim profile image
Bassem

Good point, Didn't know that before.

Collapse
 
jacksonelfers profile image
Jackson Elfers

Sometimes tests requires more creativity than the actual component being tested. It definitely inspires peace of mind. I test my own libraries more than full projects but I'm considering full coverage down the road. Nice little example. 😁

Collapse
 
jonrandy profile image
Jon Randy 🎖️

I've been a professional developer for almost 25 years - never written unit tests

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
bassemibrahim profile image
Bassem

I am not the one to ask here. Still new to unit testing.

But i would say that you need to split these large functions into smaller units that would make them easier to test.

Collapse
 
Sloan, the sloth mascot
Comment deleted
 
bassemibrahim profile image
Bassem

I don't really know any other way than refactoring the code. But i really encourage you to do it. If you have the time. Just take backup and try it out. Best of luck 🤞

Collapse
 
bassemibrahim profile image
Bassem

sure

Collapse
 
vorsprung profile image
vorsprung

I think I wrote my first unit test in 2000. That was in Java too. I used the xUnit library

Collapse
 
bogdaaamn profile image
Bogdan Covrig

Congrats! You've made your first blood, more to come.

Collapse
 
bassemibrahim profile image
Bassem

Yeah great idea and if it gets long, it won't bother anyone anyway because no one would ever call it.

 
bassemibrahim profile image
Bassem

I like trying out approaches just for the sake of it, at the least i will try it out in the future. Will definitely share my experience too. Thanks @asparallel