DEV Community

Luca Predoi
Luca Predoi

Posted on

To test or not to test, that is the question...

Introduction

When developing software an important question always arises: should I test my code? The answer is probably yes, even though most people think manually testing your code is enough. Well I'll let you in on a secret: it isn't! Unit testing is important and I believe every project that plans on being mantainable for more than 6 months should have tests.

Unit testing

benefits

Unit testing has many benefits, for example you can more confidently deploy your project into production, knowing that your code responds as expected to all edge cases. Furthermore, unit testing can help you find bugs early in the process and not in production.

Ok, but how is it done?

Generally speaking, you want to test individual components of your code, for example you have a java app and you choose to test one of your services for example OrderImplService. You will probably write unit tests for all public methods of your class, and test every edge case. Let's look at an example:

Say we have this method in our service implementation:

@Override
public void changeOrderStatus(OrderStatus status, Long oid) {
      OrderEntity order = orderRepository.findOrderByOrderId(oid)
            .orElseThrow(() -> OrderNotFoundException.notFoundById(oid))
      order.setStatus(status);
      orderRepository.save(order);
  }
Enter fullscreen mode Exit fullscreen mode

This method changes the order status for an order that has the provided order id. But how do we test it? Well we make a test class for our service OrderServiceImplTest.java

public class OrderSerivceImplTest {

   @Test 
   public void yourFirstTest(){

   }
}
Enter fullscreen mode Exit fullscreen mode

Now, our service depends on several classes, but we only care about the ones in the method that we are testing. So what we really need is the OrderRepository. But how is the repository going to respond if we have no database, because we are only testing. For that we use mocks, which basically means we mock the repository and we tell it what to do, return etc.. For that we are going to use a library called Mockito.
So let's add that in there:


@RunWith(MockitoJUnitRunner.class)
public class OrderSerivceImplTest {

   @Mock
   private OrderRepository orderRepository;

   @InjectMocks
   private OrderService orderService;

   @Test 
   public void yourFirstTest(){

   }
}
Enter fullscreen mode Exit fullscreen mode

Now we have mocked the repository and injected it into our service. Now let's create a test for our method and give it an appropriate name. I like to name tests as following: givenSomething_expectOutcome()
We also need to tell the repository what to do when we try to get an order by id. So let's implement it:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import path.to.order.repository.OrderRepository;

@RunWith(MockitoJUnitRunner.class)
public class OrderSerivceImplTest {

   @Mock
   private OrderRepository orderRepository;

   @InjectMocks
   private OrderService orderService;

   @Test 
   public void givenOrderIdAndStatus_expectChangeStatus(){     
      OrderEntity order = getOrderEntity(); 
      when(orderRepository.findOrderByOrderId(anyLong()).thenReturn(Optional.of(getOrderEntity));
      orderService.changeOrderStatus(OrderStatus.PROCCESING, "orderId")
      assertEquals(OrderStatus.PROCCESING, order.getStatus());
      verify(orderRepository).save(order);
   }

   private OrderEntity getOrderEntity(){
    .....
   }
}

Enter fullscreen mode Exit fullscreen mode

Then you should probably create a test for the case were order repository returns an empty optional. For that you have to add @Test(expected=OrderNotFoundException.class) and then make your repository return an empty optional and then delete the assert and verify.

Testing is very important and you should probably start implementing it into your projects RIGHT NOW!!

Top comments (0)