I have a BookManagementService
that uses the @Autowired
implementation of three other services, like so
@Service public class BookManagementService { private final BookRepo repo; private final BookItemRepo itemRepo; private final BookEditionRepo editionRepo; // the below services are the ones I want to mock in the test. @Autowired AuthorService authorService; @Autowired YearService yearService; @Autowired GenreService genreService; static String position = "1000"; public BookManagementService(BookRepo repo, BookItemRepo itemRepo, BookEditionRepo editionRepo, YearService yearService) { this.repo = repo; this.itemRepo = itemRepo; this.editionRepo = editionRepo; } // Rest of the methods that perform the business logic. }
So how do I mock the aforementioned services and their repo in the BookManagementServiceTest?
When the test start running and it gets to the yearService layer, it throws a NullPointerEXception cause the year it receives is null
The BookManagementServiceTest
@SpringBootTest @ExtendWith(MockitoExtension.class) class BookManagementServiceTest { // Injects the needed services @InjectMocks private BookManagementService service; @InjectMocks private YearService yearService; @InjectMocks private GenreService genreService; @InjectMocks private AuthorService authorService; // Mock the needed repos @Mock private BookItemRepo repoItem; @Mock private BookEditionRepo repoEdition; @Mock private BookRepo repo; // External repo @Mock private BookYearRepo yearRepo; @Mock private GenreRepo genreRepo; @Mock private AuthorRepo authorRepo; @BeforeEach void setUp() { // instantiate the injected services service = new BookManagementService(repo, repoItem, repoEdition, yearService); yearService = new YearService(yearRepo); genreService = new GenreService(genreRepo); authorService = new AuthorService(authorRepo); // setting the needed variables // calling when.thenReturn for all the repos like I would in a normal single class test. lenient().when(yearRepo.findByYear("2006")).thenReturn(year); lenient().when(yearRepo.save(year)).thenReturn(year); lenient().when(repoItem.save(item)).thenReturn(item); lenient().when(yearService.create("2006", edition)).thenReturn(year); lenient().when(repoEdition.save(edition)).thenReturn(edition); lenient().when(repo.save(book)).thenReturn(book); } // Tests }
Advertisement
Answer
You just have to mock all the related services aswell.
Take this as an example, imagine you want to test an ItemService class, that has ItemRepositoy and AuthService autowired.
ItemService.java
@Service public class ItemService { @Autowired private ItemRepository itemRepository; @Autowired private AuthService authService; public Item fetchItem() { return new Item(1, "name", 10, 100); } public List<Item> fetchItems() { List<Item> items = itemRepository.findAll(); Boolean isValidItems = authService.checkItems(); if (isValidItems) items.forEach((item) -> item.setValue(item.getPrice() * item.getQuantity())); return items; } }
Item.java
@Entity public class Item { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private Integer price; private Integer quantity; // getters, setters and constructors... }
AuthService.java
@Service public class AuthService { public Boolean checkItems() { return true; } }
ItemRepository.java
public interface ItemRepository extends JpaRepository<Item, Integer> { }
ItemServiceTest.java
@ExtendWith(MockitoExtension.class) public class ItemServiceTest { @InjectMocks private ItemService itemServiceMock; @Mock private ItemRepository itemRepositoryMock; @Mock private AuthService authServiceMock; @Test public void fetchItems_basic() { // arrange List<Item> items = Arrays.asList(new Item(1, "first", 10, 100), new Item(2, "second", 20, 200)); Integer expectedResultFirst = 1000; Integer expectedResultSecond = 4000; when(itemRepositoryMock.findAll()).thenReturn(items); when(authServiceMock.checkItems()).thenReturn(true); // act List<Item> actualResult = itemServiceMock.fetchItems(); // assert assertEquals(expectedResultFirst, actualResult.get(0).getValue()); assertEquals(expectedResultSecond, actualResult.get(1).getValue()); } }
If you don’t mock the autowired classes and set the when().thenReturn() as you expect you will always get a NullPointException.