Issue
I want to learn how to write JUnit tests and I fail completely.
This is my test:
@Test
public void testGetAllCustomers() {
// given
List<Customer> customerList = new ArrayList<Customer>();
customerList.add(c1);
customerList.add(c2);
customerList.add(c3);
given(customerRepository.findAll()).willReturn(customerList);
// when
List<Customer> resultList = customerService.getAllCustomers();
// then
assertThat(resultList).hasSize(3);
}
The problem is that this simple assertion already fails. The returned list is empty. I know, I am new to all of this, but the failure is so unexpected from my point of view that I have no approach on how to solve the problem.
This is the whole code (not that much):
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class CustomerServiceTests {
@Mock
private CustomerRepository customerRepository;
@InjectMocks
private CustomerService customerService;
private Customer c1 = new Customer(
1L,
"Hans Meyer",
false,
Timestamp.from(Instant.now()),
null,
null
);
private Customer c2 = new Customer(
2L,
"Marie Hollande",
true,
Timestamp.from(Instant.now()),
null,
null
);
private Customer c3 = new Customer(
3L,
"Mohammed Abbas",
false,
Timestamp.from(Instant.now()),
null,
null
);
@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
public void testGetAllCustomers() {
// given
List<Customer> customerList = new ArrayList<Customer>();
customerList.add(c1);
customerList.add(c2);
customerList.add(c3);
given(customerRepository.findAll()).willReturn(customerList);
// when
List<Customer> resultList = customerService.getAllCustomers();
// then
assertThat(resultList).hasSize(3);
}
}
The function to test is just this and I know that it works:
public List<Customer> getAllCustomers() {
return customerRepository.findAll();
}
Actually, I just want to learn how to write such tests, but for days I have been failing to write one. There are quite a few examples and explanations, but no matter what I try, I have not yet managed a working test. How to create a working test for getAllCustomers()? Thank you for your help!
Solution
Here's my recommendation: you should refactor your code and apply constructor-injection style, like this:
public class CustomerService {
private final CustomerRepository customerRepository;
public CustomerService(CustomerRepository customerRepository) {
this.customerRepository = customerRepository; // inject customerRepository via constructor
}
// ...
}
then, you don't need any Mockito annotations. Just remove them.
public class CustomerServiceTests {
private CustomerRepository customerRepository;
private CustomerService customerService;
// ... init Customer
@Before
public void setup() {
customerRepository = mock(CustomerRepository.class); // inject mocked customerRepository via constructor
customerService = new CustomerService(customerRepository);
}
@Test
public void testGetAllCustomers() {
// same as your test code
}
}
You can see that CustomerServiceTests becomes very simple and trivial to test.
Answered By - Kai-Sheng Yang
Answer Checked By - Katrina (JavaFixing Volunteer)