REST mini service problem z GET + zwracanie linków.

0
class RichBookModel {
     private BookDto bookDto;

     private AuthorDto authorDto;
}

nazwę wziąłem pierwszą z brzegu, powinna być jakaś sensowna. Ogólnie wiele zależy co chcesz osiągnąć i jak to będzie wyglądać na UI.

0

Próbuje w ten sposób ale już na etapie kontrollera :

 @RequestMapping(method = RequestMethod.POST, value = "/")
    public @ResponseBody
    void create(@Valid @RequestBody ContenerDto contenerDto) {
        bookService.saveOrUpdate(contenerDto);
    }

przekazywane są same null. Później mam tak w servisie:

@Override
    public void saveOrUpdate(ContenerDto contenerDto) {
        Author author = ContenerConverter.convertContenerDtoToAuthor(contenerDto);
        authorRepository.save(author);
        Book book = ContenerConverter.convertContenerDtoToBook(contenerDto);
        book.setAuthor(author);
        bookRepository.save(book);
    }

Muszę jakoś ustawić te dwa pola w tej metodzie? Rozwiązanie:

   @RequestMapping(method = RequestMethod.POST, value = "/")
    public @ResponseBody
    void create(@Valid @RequestBody AuthorDTO authorDTO, BookDTO bookDTO) {
        ContenerDto contenerDto = new ContenerDto();
        contenerDto.setBookDTO(bookDTO);
        contenerDto.setAuthorDTO(authorDTO);
        bookService.saveOrUpdate(contenerDto);
    }

Chyba nie jest zbyt dobre..

0

Bez sensu. a to na samym koncu to wtf...

Zrób tak:

  1. konsumujesz ContenerDto w kontrolerze (nazwe dales beznadziejną)
  2. przekazujesz ContenerDto do serwisu
  3. robisz ContenerDto.getAuthorDto i przekazujesz do odpowiedniego konwertera
  4. robisz ContenerDto.getBookDto i przekazujesz do odpowiedniego konwertera
  5. W tej chwili konwertujesz autora i zapisujesz... metoda save() na repozytorium bodajże zwraca encję uzupełnioną o ID i ten obiekt powinienes dac w book.setAuthor() a nie ten z konwersji bez ID...

ps. pomysl w jaki sposob chcialbys to zaprezentowac na widoku UI.... czemu chcesz te encje tworzyc razem ?

nie sądzę, że te Twoje saveOrUpdate dzialają poprawnie.

odnosze wrażenie, że robisz to z lekka bezmyślnie. Może lepiej byłoby nieco bardziej zrozumiec w kontekscie bazodanowym ? repozytorium springowe to spora abstrakacja ale chyba nie do końca rozumiesz co i jak.

0

Dzięki za ostre słowa ale pewnie się przyda :). Pomyślałem, ze jak ktoś będzie wprowadzał książkę to będzie chciał dodać od razu autora ale w zasadzie nadal mogę to zrealizować bez zespalania dwóch encji.

0
mat90 napisał(a):

Dzięki za ostre słowa ale pewnie się przyda :). Pomyślałem, ze jak ktoś będzie wprowadzał książkę to będzie chciał dodać od razu autora ale w zasadzie nadal mogę to zrealizować bez zespalania dwóch encji.

Możesz mieć na widoku UI :

  1. tworzenie autora
  2. następnie np. wybór autora z listy rozwijalnej - przy tworzeniu nowej ksiazki , wtedy zaciągasz juz istniejacego autora i zapisujesz relacje z ksiazka

dalej:
3. wedlug Twoich warstw jakie masz, powinienes raczej logike trzymac bardziej w serwisie, w kontrolerze tylko wywolanie serwisu
4. dto i encje masz w jednym pakiecie. Dlaczego?
5. nie masz testów w ktorych np. przetestowalbys Twoje createOrUpdate i ktore pokazaloby Ci szybko, że to nie działa poprawnie
6. w tej chwili pewnie testujesz to wszystko uruchamiając aplikacje, co jest słabe.

0

Próbuje uporządkować kod i zrobić, że jednak dwie encje osobno no ale jak chce dodać książkę do chcę dodać znane mi id autora.
Mam kod:

@Override
    public Book createBook(BookDto bookDto) {
        Author author = authorRepository.findOne(bookDto.getAuthor_id());
        Book book = BookConverter.convertBookDtoToBook(bookDto);
        book.setAuthor(author);
        return bookRepository.save(book);
    }

Który nie do końca wiem dlaczego nie działa. Testy próbuje pisać ale próbuje to dobre słowo.

1

Czlowieku. Ale co nie dziala? Opisz to. Jakis stacktrace?
Kontroler nic nie zwraca? Nie dodaje nic sie w bazie?
Uzywasz debugera w ogole? Laczyles sie do swojej bazy by sprawdzic czy sa tam te wpisy? - testy bylyby lepsze.

Moglbys laskawie poczytac o springu i hibernate. Bo zamiast zrozumiec robisz bezmyslnie co Ci pisze.

W tym przypadku nie powinienes musiec wolC findOne na author repository, w koncu zapisujesz s tabelce tylko ID. W entity managerze jest getReference. Zapomnialem co bylo w spring data.

0

Trochę widzę, że się zdenerwowałeś. Tak, staram się używać debuggera :). Teraz działa. Zmieniłem metodę na:

public void createBook(BookDto bookDto) {
        Book book = BookConverter.convertBookDtoToBook(bookDto);
        book.setAuthor(authorRepository.getOne(bookDto.getAuthor_id()));
        bookRepository.save(book);
    }

i jest ok. Już wcześniej kombinowałem ale problem był inny - zapomniałem dodać adnotacji @Autowired przy ustawianiu authorRepository - to tak jakby ktoś pytał.
Dziękuje Ci za pomoc tylko bez nerwów proszę.

0

Uczenie sie w taki sposob jest nieefektywne.
Piszesz cos nie wiadomo po co i byle jak i w zasadzie widac, ze starasz sie cos zrobic by jakos dzialalo bez szczegolnego zrozumienia.

Dlatego powinienes poczytac a pozniej zadawac pytania.
I naucz sie testy pisac.

I moglbys rozdzielic kontrolery na book i author controller.

0

Mam rozdzielone.

0
mat90 napisał(a):

Mam rozdzielone.

Wczesniej miales api controller.

0

Mam kolejne pytanie odnośnie testów. Jak one powinny wyglądać, jakich bibliotek używać?
Póki co moja klasa testowa (napisałem jak umiałem) wygląda tak: https://github.com/MatDevCode/LibraryWebService/blob/master/src/test/java/com/matdevcode/librarywebservice/LibrarywebserviceApplicationTests.java
Testy wydaje mi się, że spełniają swoją rolę ale czy tak one powinny wyglądać? Czy inaczej? Czy mockito byłoby w tym przypadku wskazane? Proszę o jakieś podpowiedzi.

1

AssertJ - dla lepszych asercji
Mockito - by mockowac obiekty (tam gdzie to ma sens)
Integracyjne - w Twoim przypadku ze wstawaniem kontekstu Springa

Warto też spojrzeć na :
Spock - czyli zastepuje Mockito i AssertJ , ale to jest groovy
RestAssured - do testowania restow

0

Czyli w tym przypadku do testowania mojego rest kontrolera bedzie wykorzystac RestAssured?
Druga sprawa, napiales ze mockowanie wtedy kiedy ma to sens? Czyli wtedy kiedy np. korzystamy z czegos "zewnetrznego"?

0

Java nie wspiera definiowania własnych klas, że trzeba robić jakieś Mapy, a potem dobierać się do pól po nazwie?

Czy to test integracyjny? Bo jeśli tak, to trochę dziwnie wyglądają testy typu deleteBookTest, który wygląda jakby odbywał się ramach jednego UoW. Test może przejść, a dane z bazy nie zostaną usunięte, bo wszystko nie wyjdzie nawet poza ORMa.
No chyba, że nie ma ORMa ani UoW, to wtedy wszystko ok.

0

Korzystam z jpa repository. Test przechodzi a z bazy danych znika jeden rekord..

0

1.raczej nie musisz budowac zadnych map. Mozesz normalnie po obiektach...
2.moze podziel troche ten plik zamiast trzymac wszystko w jednym?
3. By przetestowac kontroller mozesz uzyc testresttemplate, moze byc rest assured, cokolwiek
4.ta. Mockujesz chocby jakies zewnetrzne wywolania

0

To jeszcze dla pewności. Chce napisać testy odnowa ale nie wiem czy dobrze rozumiem.
Otóż czyli w tym przypadku mógłbym to rozbić np. dla klasy testowe:

  1. testowanie np. konwerterów (to tak o, żeby zrozumieć), te testy jednostkowe sprawdzały by czy jeden obiekt jest mapowany na drugi tak jak ja chce i tyle.
  2. testowanie serwisów czyli przykładowy test sprawdzający metodę w servisie odpowiadającą za utworzenie nowego obiektu w bazie danych powinien wyglądać koncepcyjnie tak:
    tworze obiekt BookDTO, akcja: odpalenie metody createBook i sprawdzam czy mam to co oczekiwałem w bazie danych.
  3. testowanie kontrolera rest - np. sprawdzam czy metoda get zwraca kod 200 i czy jest to obiekt w moim przypadku BookDto ale czy powinienem sprawdzać czy pokrywa to się z bazą danych? Bo w zasadzie to powinno być przetestowane wyżej.

A testy integracyjne to byłyby takie , że sprawdzam większy zbiór funkcjonalności, czyli np. kreowanie nowej encji ale zaczynając od samego kontrolera? Czyli przekazuję obiekt metodą POST na danym url, następnie patrze czy zapisało się to również w bazie danych. I czy zapisało się to tak jak bym tego oczekiwał. Dobrze to rozumiem?

Jeżeli tak czy ktoś mi powie co mógłbym mockowa w punktach 1,2,3? Czy nic. Myślę, że rozumiem na czym polega mockowanie ale chciałbym wiedzieć kiedy należałoby tego używać, kiedy to ma sens.

Pozdrawiam

1
  1. Nie, bo test z bazą danych to już jakby nie patrzeć test integraycjny. Testy serwisów/logiki powinny testować tą logikę właśnie.
  2. Nie ma sensu testować kontrolera, bo nie powinno byc w nim zadnej logiki wartej testowania.
0
Shalom napisał(a):
  1. Nie, bo test z bazą danych to już jakby nie patrzeć test integraycjny. Testy serwisów/logiki powinny testować tą logikę właśnie.
  2. Nie ma sensu testować kontrolera, bo nie powinno byc w nim zadnej logiki wartej testowania.

odnośnie testow kontrolera to przeciez mozesz testowac sam kontroler i samą jego komunikację i chocby kody błędów czy dobre zwraca itp.

0

Ale co to znaczy testować kontoler? Kontroler powinien wyglądać tak:

public Cośtam magicRestCall(whatever){
    return domainService.getData();
}

Albo tak:

public ModelAndView magicCall(whatever){
    return new ModelAndView(domainService.getData(), "viewName");
}

Co konkretnie chcesz tu testować? Jest bardzo niewiele sytuacji kiedy ma jakiś sens pisanie testów kontrolera. W 99% przypadków takie testy to są testy biblioteki/frameworka którego ktoś uzywa, a nie testy własnego kodu. Np. ktoś namiętnie testuje czy Spring MVC i Jackson działaja poprawnie i czy zwrócą mu poprawnego jsona przy wejściu na dany URL :D

0

Czyli generalnie w tym przypadku testy integracyjne?

0
mat90 napisał(a):

Korzystam z jpa repository. Test przechodzi a z bazy danych znika jeden rekord..

A jak sprawdzasz, że znika? W którym momencie znika, od razu po usunięciu, czy po zakończeniu testu? Bo nie pytasz o to bazy danych tylko to swoje repository...

Jeśli nie masz zatwierdzania transakcji, a z bazy znika rekord, to znaczy, że nie masz UoW. Ja wiem, że Java i Spring to bida z nędzą, ale bez przesady.
No chyba, że transakcja jest automatycznie zatwierdzana po wyjściu z metody testującej, ale to znaczy z kolei, że nie testujesz tego, co chcesz, a jakaś zmiana w konfiguracji może sprawić, że operacje na bazie przestaną działać.

mat90 napisał(a):

To jeszcze dla pewności. Chce napisać testy odnowa ale nie wiem czy dobrze rozumiem.
Otóż czyli w tym przypadku mógłbym to rozbić np. dla klasy testowe:

  1. testowanie np. konwerterów (to tak o, żeby zrozumieć), te testy jednostkowe sprawdzały by czy jeden obiekt jest mapowany na drugi tak jak ja chce i tyle.

Co dają unit testy konwerterów, które będą dość żmudne do napisania, czego nie dadzą testy integracyjne? Zastanów się, czy jest to warte poświęcenia czasu. W przypadku CRUDa przydatność testów jednostkowych jest naprawdę niewielka. Testy mogą przechodzić, ale w praktyce i tak liczy się tylko to, co jest w bazie i w GUI, a tego nie sprawdzisz inaczej niż integracyjnie.

Jeżeli tak czy ktoś mi powie co mógłbym mockowa w punktach 1,2,3? Czy nic. Myślę, że rozumiem na czym polega mockowanie ale chciałbym wiedzieć kiedy należałoby tego używać, kiedy to ma sens.

Np. kiedy testujesz jakąś logikę, która przetwarza dane i wymaga do tego dostępu do zewnętrznych zasobów (spoza Twojej aplikacji). Ale praktycznie zawsze warto pisać taki kod przetwarzający dane w sposób niewymagający dostępu do zewnętrznych zasobów podczas samego procesu przetwarzania, i wtedy przydatność mocków jest niewielka.

0

Co konkretnie chcesz tu testować? Jest bardzo niewiele sytuacji kiedy ma jakiś sens pisanie testów kontrolera. W 99% przypadków takie testy to są testy biblioteki/frameworka którego ktoś uzywa, a nie testy własnego kodu. Np. ktoś namiętnie testuje czy Spring MVC i Jackson działaja poprawnie i czy zwrócą mu poprawnego jsona przy wejściu na dany URL :D

np. walidacje na jakies pole czy cokolwiek. Po prostu poprawna komunikacje. Czy zwrocil odpowiedni status code przy bledzie itp.
I uważam, że warto. Podobnie jeśli klient poprawnie uderza do mocka.

czemu ? bo uniknąć można durnych błędów typu copy paste . A test naklepać nietrudno i jest dość szybki.

i tak, mockuje sobie np. , że serwis rzuca np. NotFound itp.

0
Krzywy kr napisał(a):

czemu ? bo uniknąć można durnych błędów typu copy paste .

Nie prościej ich uniknąć po prostu nie robiąc copy-paste?

A test naklepać nietrudno i jest dość szybki.

Tylko potem trzeba to utrzymywać i zmieniać przy każdej refaktoryzacji, a ich wynik jest zazwyczaj false-negative.

i tak, mockuje sobie np. , że serwis rzuca np. NotFound itp.

I piszesz w kontrolerze, że jeśli serwis rzucił NotFound, to kontroler ma zwrócić NotFound, a jeśli jest ok, to ok?
Bo jak dla mnie, to nadal tu nie ma czego testować. A takie rzeczy można załatwić generycznie, jakimś action filtrem czy czymś takim dla całej aplikacji, a nie bawić się w ifologię każdego kontrolera.

0
somekind napisał(a):

Nie prościej ich uniknąć po prostu nie robiąc copy-paste?

i zaufać ludziom ?

A test naklepać nietrudno i jest dość szybki.

I piszesz w kontrolerze, że jeśli serwis rzucił NotFound, to kontroler ma zwrócić NotFound, a jeśli jest ok, to ok?
Bo jak dla mnie, to nadal tu nie ma czego testować. A takie rzeczy można załatwić generycznie, jakimś action filtrem czy czymś takim dla całej aplikacji, a nie bawić się w ifologię każdego kontrolera.

nie wiem gdzie ma się tam pojawić ifologia.
Czyli ludzie, którzy tworzą frameworki testowe do RESTów robią to zupełnie bez sensu ?

0
Krzywy kr napisał(a):

i zaufać ludziom ?

No, to jeśli to jest problemem, to może pora przestać pracować w januszsofcie, zmienić zespół na złożony z ludzi zdolnych do trzymania się ustalonych zasad, albo zacząć robić review. Tak czy siak, to problem procesów w firmie, a nie kodu.

nie wiem gdzie ma się tam pojawić ifologia.

Jeśli nie ma ifologii, to nie ma co testować, bo kontroler zwraca po prostu to, co dostaje z serwisu.

Czyli ludzie, którzy tworzą frameworki testowe do RESTów robią to zupełnie bez sensu ?

Nie wiem, za to wielu programistów lubi buzword driven development i popadanie w skrajności takie jak pisanie testów jednostkowych do wszystkiego, nawet jeśli nie wnoszą żadnej wartości dodanej.

0
somekind napisał(a):
Krzywy kr napisał(a):

i zaufać ludziom ?

No, to jeśli to jest problemem, to może pora przestać pracować w januszsofcie, zmienić zespół na złożony z ludzi zdolnych do trzymania się ustalonych zasad, albo zacząć robić review. Tak czy siak, to problem procesów w firmie, a nie kodu.

Sam jestes januszsoft.
Ludzie nawet najlepsi się mylą i zapomną choćby napisać jakiejś głupiej adnotacji czy cokolwiek. A w CR można tego nie zauważyć.
Zadania jak napisac kontroler to nie jest jakies wyzwanie, dlatego ludzie sie przy czyms takim specjalnie nie skupiają, więc podatne na proste błędy.
Sobie też nie ufam.

0
Krzywy kr napisał(a):

Sam jestes januszsoft.

Argumentacja level Java. :D

Ludzie nawet najlepsi się mylą i zapomną choćby napisać jakiejś głupiej adnotacji czy cokolwiek. A w CR można tego nie zauważyć.

I jak niby testy, które też można napisać błędnie albo o nich zapomnieć, temu przeciwdziałają?

0
somekind napisał(a):
Krzywy kr napisał(a):

Sam jestes januszsoft.

Argumentacja level Java. :D

Ludzie nawet najlepsi się mylą i zapomną choćby napisać jakiejś głupiej adnotacji czy cokolwiek. A w CR można tego nie zauważyć.

I jak niby testy, które też można napisać błędnie albo o nich zapomnieć, temu przeciwdziałają?

Sprawiaja, że trzeba wiecej pomyslec.

Wyzwiska level C#.

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