Testowanie metody z wykorzystaniem mockito

0

Witam,
mam do przetestowania metodę w której dodaję jeden obiekt do drugiego. Z mockito i junit nie mam zbyt dużego doświadczenia i mam sporę kłopoty bo test nie chce przejść.
To jest moja metoda w serwisie:

@Transactional
	public void addPersonsToTeams(Long teamId, Long personId) {
		Assert.notNull(personId, "Object can't be null!");
		Assert.notNull(teamId, "Object can't be null!");
		try {
			Person person = personRepository.getOne(personId);
			Team team = teamRepository.getOne(teamId);
			person.getTeams().add(team);
			personRepository.save(person);
		} catch (Exception e) {
			throw new CreateEntityException();
		}
		
	}

A tak wygląda mój test który nie działa:

	@Test
	public void shouldAddPersonToTeam() {
		Team team = new Team(1l, "TestCase1", "Description1", "Krakow", 12);
		Person person = new Person(1L, "jan", "mucha", "krakow", "[email protected]", "Programing", "Developer");
		
		teamService.createTeam(mapper.map(team, TeamDto.class));
		personService.addPerson(mapper.map(person, PersonDto.class));
		personRepository.getOne(team.getId());
		teamRepository.getOne(person.getId());
		teamService.addPersonsToTeams(team.getId(), person.getId());
		
		verify(teamRepository, times(1)).save(team);
		verify(personRepository, times(1)).save(person);
		
	}
0

Nie mam całego kodu i nie wrzuciłeś błędu, ale tutaj w ogóle nie widzę mockowania.
Tutaj chyba nie jest problemem mockowanie, tylko pewnie nie masz bazy danych w testach.
Skoro chcesz przetestować w ten sposób serwis, to chyba nie chodzi o mocki.
Dobrą praktyką jest np. uzywanie bazy H2 na potrzeby testów.
Nie podam Ci kodu konfiguracji springa, nie pamiętam, musisz pogooglać.

0

To może faktycznie wrzucę cały kod:) wszystkie testy przechodzą poza testem metody shouldAddPersonToTeam:

public class TeamServiceTest {
	private TeamService teamService;
	private ModelMapper mapper;
	private PersonService personService;

	@Mock
	private TeamRepository teamRepository;
	private PersonRepository personRepository;
	
	@Before
	public void setUp() {
		MockitoAnnotations.initMocks(this);
		this.mapper = new ModelMapper();
		teamService = new TeamService(teamRepository, this.mapper);
		personService = new PersonService(personRepository, this.mapper);
		
	}
	
	@Test
	public void shouldReturnAllTeams() {
		initMockServiceTest();
		
		List<TeamDto> resultTeamDtos = teamService.findAll();
		assertThat(resultTeamDtos)
				.extracting("name", "description", "city", "headcount")
				.contains(
						tuple("Name1", "description1", "city1", 2),
						tuple("Name2", "description2", "city2", 5));
	}
	
	@Test
	public void shouldReturnTeamById() {
		Team team1 = new Team(1l, "Name1", "description1", "city1", 2);
		
		when(teamRepository.findById(1l)).thenReturn(Optional.ofNullable(team1));
		Optional<TeamDto> teamById = teamService.findTeamById(1l);
		
		assertThat(teamById.get().getId()).isEqualTo(1l);
		assertThat(team1.getCity()).isEqualTo(teamById.get().getCity());
	}
	
	@Test
	public void shouldNotReturnTeamWithNoId() {
		when(teamRepository.findById(null)).thenThrow(new IllegalArgumentException("An argument is missing ! "));
		
		assertThatExceptionOfType(IllegalArgumentException.class)
				.isThrownBy(() -> teamService.findTeamById(null))
				.withMessage("ID must exist ");
	}
	
	@Test
	public void shouldNotReturnTeamByGivenId() {
		when(teamRepository.findById(2l)).thenReturn(Optional.empty());
		
		Optional<TeamDto> teamById = teamService.findTeamById(2l);
		
		assertThat(teamById).isEmpty();
	}
	
	@Test
	public void shouldAddTeamToDatabase() {
		Team team1 = new Team(1l, "Name1", "description1", "city1", 2);
		
		teamService.createTeam(mapper.map(team1, TeamDto.class));
		
		verify(teamRepository, times(1)).save(team1);
	}
	
	@Test
	public void shouldNotAddTeamToDatabase() {
		when(teamRepository.save(null)).thenThrow(new IllegalArgumentException());
		
		assertThatExceptionOfType(IllegalArgumentException.class)
				.isThrownBy(() -> teamService.createTeam(null))
				.withMessage("Object can't be null!");
	}
	
	@Test
	public void shouldDeleteTeamById() {
		teamService.deleteTeamById(1l);
		
		verify(teamRepository, times(1)).deleteById(1l);
	}
	
	@Test
	public void shouldNotDeleteTeamById() {
		doThrow(new IllegalArgumentException()).when(teamRepository).deleteById(null);
		
		assertThatExceptionOfType(IllegalArgumentException.class)
				.isThrownBy(() -> teamService.deleteTeamById(null))
				.withMessage("Id can't be null !");
	}
	
	@Test
	public void shouldNotDeleteWhenTeamNotExist() {
		doThrow(new IllegalStateException()).when(teamRepository).deleteById(11l);
		
		assertThatExceptionOfType(IllegalStateException.class)
				.isThrownBy(() -> teamService.deleteTeamById(11l))
				.withMessage("Team with given id, does not exist ! ");
	}
	
	@Test
	public void shouldUpdateTeamInDatabase() {
		Team team1 = new Team(1l, "Name1", "description1", "city1", 2);
		
		when(teamRepository.save(team1)).thenReturn(team1);
		when(teamRepository.findById(1l)).thenReturn(Optional.of(team1));
		when(teamRepository.getOne(1l)).thenReturn(team1);
		
		teamService.updateTeamById(1l, mapper.map(team1, TeamDto.class));
		
		verify(teamRepository, times(1)).save(team1);
		verify(teamRepository, times(1)).findById(1l);
		verify(teamRepository, times(1)).getOne(1l);
	}
	
	@Test
	public void shouldNotUpdateTeamToDatabase() {
		TeamDto teamDto = new TeamDto(1l, "TestCase1", "Description1", "Krakow", 12);
		
		when(teamRepository.findById(1l)).thenThrow(new NoEntityFoundException());
		when(teamRepository.findById(2l)).thenThrow(new IllegalArgumentException());
		when(teamRepository.findById(null)).thenThrow(new IllegalArgumentException());
		
		assertThatExceptionOfType(NoEntityFoundException.class)
				.isThrownBy(() -> teamService.updateTeamById(1l, teamDto))
				.withMessage("There is no Entity in database with given id.");
		assertThatExceptionOfType(IllegalArgumentException.class)
				.isThrownBy(() -> teamService.updateTeamById(null, teamDto))
				.withMessage("Id can't be null ! ");
		assertThatExceptionOfType(IllegalArgumentException.class)
				.isThrownBy(() -> teamService.updateTeamById(2l, null))
				.withMessage("Object can't be null!");
	}

	@Test
	public void shouldAddPersonToTeam(){
		Team team = new Team(1L, "TestCase1", "Description1", "Krakow", 12);
		Person person = new Person(1L, "jan", "mucha", "krakow", "[email protected]", "Programing", "Developer");

		doReturn(team).when(teamRepository).getOne(1L);
		doReturn(person).when(personRepository).getOne(1L);

		teamService.createTeam(mapper.map(team, TeamDto.class));
		personService.addPerson(mapper.map(person, PersonDto.class));

		teamService.addPersonsToTeams(team.getId(), person.getId());

		verify(teamRepository).save(team);
		verify(personRepository).save(person);
	}
	
	private void initMockServiceTest() {
		Team team1 = new Team(1l, "Name1", "description1", "city1", 2);
		Team team2 = new Team(1l, "Name2", "description2", "city2", 5);
		
		when(teamRepository.findAll()).thenReturn(Arrays.asList(team1, team2));
	}
}

Kod błędu jaki się pojawia to :
org.mockito.exceptions.misusing.NullInsteadOfMockException:
Argument passed to when() is null!
Example of correct stubbing:
doThrow(new RuntimeException()).when(mock).someMethod();
Also, if you use @mock annotation don't miss initMocks()

0

Szczerze, to nie wiem na pierwszy rzut oka.
Masz MockitoAnnotations.initMocks(this), więc to chyba nie potrzebne, ale spróbuj nad klasą dodać adnotację @RunWith(MockitoJUnitRunner.class), może pomoże.

1

To teraz możesz zwiększyć jakość kodu w projekcie pozbywając się zbędnego kodu. Bo ten cały zestaw testów nie pokrywa ani jednego faktycznie możliwego do wystąpienia błędu. Jedyne co tutaj testujesz to Mockito, kolekcje, wywoływanie metod i poprawność działania statycznego typowania.

0

@rdunia: a co może się stać, że nie doda? Metoda add w kolekcji przestanie nagle działać? Wtedy wszyscy będą mieli przechlapane.

A w przypadku negatywnym: when(teamRepository.save(null)).thenThrow(new IllegalArgumentException()); - to Ty implementowałeś metodę save i rzucasz z niej wyjątek?

0

@rdunia87 nie widzimy reszty kodu, ale idę o zakład że te TeamService i PersonService są do wrzucenia, bo nie robią nic, poza delegowaniem wywołań do tych DAO/Repository. Nie ma tam logiki = nie ma w ogóle sensu trzymać ani testować takiego kodu.
Na oko to lecisz z jakiegoś crudowego tutoriala gdzie ludzie wpychają różne Service tylko po to żeby je mieć, bo logiki tam żadnej nie ma...

1 użytkowników online, w tym zalogowanych: 0, gości: 1