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
}
CodePudding user response:
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.