Reputation: 63
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
}
Upvotes: 4
Views: 4954
Reputation: 331
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.
Upvotes: 3