Test metody dodawania elementu do bazy danych nie działa

0

Witam,
mam prosty webservice z crudem który działa, ale problem jest z metodą testującą dodawanie nowego elementu. Nie wiem jak to ugryźć.

Moja metoda wygląda tak:

 	public Optional<PersonDto> addPerson(PersonDto personDto) {
		Assert.notNull(personDto, "personDto can't be null");
		Person person = personRepository
				.save(modelMapper.map(personDto, Person.class));
		return Optional.of(modelMapper.map(person, PersonDto.class));
	}

A test wygląda tak:

	@Test
	public void shouldAddPersonToDatabase() {
		Person person1 = new Person(1L, "jan", "mucha", "krakow", "[email protected]", "Programing", "Developer");
		personService.addPerson(mapper.map(person1, PersonDto.class));
		Mockito.verify(personRepository, times(1)).save(person1);
	}

Niestety przy tak napisanym kodzie pojawia się taki o to problem:

java.lang.IllegalArgumentException: source cannot be null

	at org.modelmapper.internal.util.Assert.notNull(Assert.java:53)
	at org.modelmapper.ModelMapper.map(ModelMapper.java:370)
	at com.softwaremind.crew.people.service.PersonService.addPerson(PersonService.java:85)
	at com.softwaremind.crew.people.service.PersonServiceTest.shouldAddPersonToDatabase(PersonServiceTest.java:75)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

2

Pewnie na górze masz żałosne @Mock PersonReporistory personRepository, a jego metoda save domyślnie zwraca null.

Przy okazji: Testowanie serwisów przy pomocy zamokowanych repozytoriów bazodanowych mówi tyle o ich działaniu co zdjęcia profilowe w serwisach randkowych o urodzie właścicieli/lek.
(Coś tam można wywnioskować, ale....)

0

Czemu żałosne? tak mam takie rozwiązanie wydawało mi się że jest to optymalne. Problem pojawił się jak wprowadziłam asercje w klasie serwisowej, model maper został wstrzyknięty jako bean w klasie konfiguracyjnej:

Klasa testowa na górze wygląda następująco:

	private PersonService personService;
	private ModelMapper mapper;
	
	@Mock
	private PersonRepository personRepository;
	
	@Before
	public void initTest() {
		MockitoAnnotations.initMocks(this);
		mapper = new ModelMapper();
		personService = new PersonService(personRepository, this.mapper);

	}

	@Before
	public void initMockRepository() {
		Person person1 = new Person(1L, "jan", "mucha", "krakow", "[email protected]", "Programing", "Developer");
		Person person2 = new Person(1L, "Alicja", "Kowalska", "Warszawa", "[email protected]", "Business", "Designer");
		Mockito.when(personRepository.findAll()).thenReturn(Arrays.asList(person1, person2));
	}
0

Jak zmieniłam metodę dodawania na taką :

public void addPerson(PersonDto personDto) {
		Assert.notNull(personDto);
		Assert.notNull(personDto.getFirstName());
		personRepository.save(modelMapper.map(personDto, Person.class));
	}

Ale szkoda bo chciałam wykorzystać mapowanie żeby cały kod był spójny a teraz połowa metod jest robiona z wykorzystaniem javy 8 a druga połowa z taka. Dodatkowo caly restcontroller poszedł do zmiany. Lipa

1

Żeby Ci to zadziałało to musiałbyć jeszcze dodać:
w tym stylu.
Mockito.when(personRepository.save(anyObj())).thenAnswer (inv ->invocation.getArgumentAt(0, Person.class));

(Sorry, pisze z pamięci i nie używam Mockito w normalnych projektach, więc mogą być jakieś błędy).

A **żałosne **odnosiło się do moim zdaniem niskiej skuteczności takich testów na Mockach.
Przetestujesz Mockito ,ale ono już ma naprawdę miliony testów popisanych. Tysiace programistów na całym świecie pisze codziennie nowe testy do mockito. Moim zdaniem nie warto się dokładać.

Poza tym zawsze mam watpliwości jak widzę coś w stylu:
Mockito.verify(personRepository, times(1)).save(person1);

Jeśli potrafię tak napisać tą metodę, że zapisze się w bazie bez wywoływania save.. to czy to jest faktycznie błąd?

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