Cześć, bawię się trochę w refactor testów w celu zwiększenia ich czytelności. Miałbym dwa pytania, zobrazujmy sobie je na przykładzie. Oto klasa którą testuję:
@Component class CookieDeleterImpl implements CookieDeleter { @OverRide public void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name) { Cookie[] cookies = request.getCookies(); if (cookies != null) { Arrays.stream(cookies) .filter(cookie -> name.equals(cookie.getName())) .forEach(cookie -> { cookie.setValue(null); cookie.setMaxAge(0); cookie.setPath("/"); response.addCookie(cookie); }); } } } Klasa testowa:
public class CookieDeleterImplTest { private CookieDeleterImpl deleter; private MockHttpServletRequest request; private MockHttpServletResponse response; @BeforeEach void setUp() { deleter = new CookieDeleterImpl(); request = new MockHttpServletRequest(); response = new MockHttpServletResponse(); } @test void whenCookiePresent_Delete() { addCookieToRequest("cookie", "value");
assertCookieDeleted(response, "cookie"); } private void addCookieToRequest(String name, String value) { Cookie cookie = new Cookie(name, value); request.setCookies(cookie); } private void assertCookieDeleted(MockHttpServletResponse response, String cookieName) { Cookie[] cookies = response.getCookies(); assertNotNull(cookies); assertTrue(Arrays.stream(cookies).anyMatch(cookie -> cookieName.equals(cookie.getName()) && cookie.getMaxAge() == 0 && cookie.getValue() == null), "Cookie should be set to deleted"); } } 1. Czy test dla Was jest czytelny i zrozumiały ? Zastanawiam się, czy zbyt dużo szczegółów nie przeniosłem do metod pomocniczych. 2. Czy metody pomocnicze powinienem przenieś do oddzielnej klasy, czy też w sytuacji, gdzie jest mało testów, mogą zostać w klasie testowej? #java #spring #naukaprogramowania
@Kamishimi: kod nie jest dla mnie ani czytelny ani zrozumiały. Pytania, które mi się nasuwają: 1. O co w ogóle chodzi? Usuwanie ciasteczek? To ma być klient czy serwer http? Klient może go po prostu nie wysłać, serwer nie ustawiać, więc o co kaman? 2. Usuwanie ciasteczek? To co oznacza "Cookie should be set to deleted"?
@Bordomir: Proces usuwania ciasteczek odnosi się do serwera HTTP. W projekcie wykorzystuję JWT dla autentykacji użytkowników. W momencie logowania, tworzę ciasteczko zawierające ten token, które jest następnie wykorzystywane do autentykacji. Gdy użytkownik decyduje się na wylogowanie, chcę wysłać polecenie do przeglądarki klienta, aby usunęła to ciasteczko z tokenem.
@Kamishimi: uwierzytelnienia*, autentykacja to kalka językowa i błąd.
Web serwer nie ma możliwości wysyłania żadnych poleceń do przeglądarki - takie rzeczy załatwia się w nagłówkach protokołu HTTP. Nie lepiej uczyć się na realnych przykładach?
@Bordomir: Może trochę źle napisałem. W mojej implementacji, proces usuwania ciasteczka realizowany jest przez ustawienie nagłówka Set-Cookie w odpowiedzi HTTP. Kiedy użytkownik decyduje się na wylogowanie, serwer wysyła odpowiedź z ciasteczkiem, w którym Max-Age jest ustawione na 0, a wartość ciasteczka na null.
@Kamishimi: odpisywałem tylko w odniesieniu do Twojego fragmentu kodu - że on jest dla mnie nie zrozumiały. Jak mówisz, że chodzi o symulację wylogowania, to rozumiem znacznie więcej.
Oczywiście masz rację z tym, że jakaś część przeglądarek zareaguje na to co ustawiłeś i w zależności od konfiguracji - usunie ciasteczko po stronie klienta.
Teraz nie rozumiem tylko jednego - dlaczego miałbyś się upewniać, że ciasteczko istnieje? Da się wylogować nie
@Kamishimi po prostu metoda jest czytelniejsze od asercji czysto javowych, tam podajesz 2 argument po przecinku i ciężko czasem zobaczyć ten przecinek w assertJ jest to lepiej zrobione
@Kamishimi: wydaje się dużo lepiej imo. możesz jeszcze dodać verify(response, times(1)).addCookie(any(Cookie.class)); oraz assertThat(optionalCookie).isPresent(); przed assertami optionala.
bawię się trochę w refactor testów w celu zwiększenia ich czytelności. Miałbym dwa pytania, zobrazujmy sobie je na przykładzie.
Oto klasa którą testuję:
@Componentclass CookieDeleterImpl implements CookieDeleter {
@OverRide
public void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
Arrays.stream(cookies)
.filter(cookie -> name.equals(cookie.getName()))
.forEach(cookie -> {
cookie.setValue(null);
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
});
}
}
}
Klasa testowa:
public class CookieDeleterImplTest {
private CookieDeleterImpl deleter;
private MockHttpServletRequest request;
private MockHttpServletResponse response;
@BeforeEach
void setUp() {
deleter = new CookieDeleterImpl();
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
}
@test
void whenCookiePresent_Delete() {
addCookieToRequest("cookie", "value");
deleter.deleteCookie(request, response, "cookie");
assertCookieDeleted(response, "cookie");
}
private void addCookieToRequest(String name, String value) {
Cookie cookie = new Cookie(name, value);
request.setCookies(cookie);
}
private void assertCookieDeleted(MockHttpServletResponse response, String cookieName) {
Cookie[] cookies = response.getCookies();
assertNotNull(cookies);
assertTrue(Arrays.stream(cookies).anyMatch(cookie ->
cookieName.equals(cookie.getName()) &&
cookie.getMaxAge() == 0 &&
cookie.getValue() == null),
"Cookie should be set to deleted");
}
}
1. Czy test dla Was jest czytelny i zrozumiały ? Zastanawiam się, czy zbyt dużo szczegółów nie przeniosłem do metod pomocniczych.
2. Czy metody pomocnicze powinienem przenieś do oddzielnej klasy, czy też w sytuacji, gdzie jest mało testów, mogą zostać w klasie testowej?
#java #spring #naukaprogramowania
@Kamishimi: czemu dodajesz puste cookie do responsa i czemu w ogole czyścisz request z cookiesów?
Jak chcesz nie dodawac w responsie cookiesów po prostu ich nie ustawiaj xD
Pytania, które mi się nasuwają:
1. O co w ogóle chodzi? Usuwanie ciasteczek? To ma być klient czy serwer http? Klient może go po prostu nie wysłać, serwer nie ustawiać, więc o co kaman?
2. Usuwanie ciasteczek? To co oznacza "Cookie should be set to deleted"?
Also, fatalny angielski w tej [:-3] linijce.
//given
//when
//then
nazwa testu moze byc typu: ShouldRemoveCookieIfExist, ShouldThrowAnErrorWhen.. itd
Czemu?
Proces usuwania ciasteczek odnosi się do serwera HTTP.
W projekcie wykorzystuję JWT dla autentykacji użytkowników. W momencie logowania, tworzę ciasteczko zawierające ten token, które jest następnie wykorzystywane do autentykacji. Gdy użytkownik decyduje się na wylogowanie, chcę wysłać polecenie do przeglądarki klienta, aby usunęła to ciasteczko z tokenem.
Ten kontroler odpowiada za
Web serwer nie ma możliwości wysyłania żadnych poleceń do przeglądarki - takie rzeczy załatwia się w nagłówkach protokołu HTTP. Nie lepiej uczyć się na realnych przykładach?
Czy to jest złe podejście ?
Oczywiście masz rację z tym, że jakaś część przeglądarek zareaguje na to co ustawiłeś i w zależności od konfiguracji - usunie ciasteczko po stronie klienta.
Teraz nie rozumiem tylko jednego - dlaczego miałbyś się upewniać, że ciasteczko istnieje? Da się wylogować nie
assertTrue(Arrays.stream(cookies).anyMatch(cookie ->cookieName.equals(cookie.getName()) &&
cookie.getMaxAge() == 0 &&
cookie.getValue() == null),
@testvoid whenCookiePresent_Delete() {
Cookie cookie = new
@testvoid whenCookiePresent_Delete() {
Cookie cookie = new Cookie("cookie",
verify(response, times(1)).addCookie(any(Cookie.class));orazassertThat(optionalCookie).isPresent();przed assertami optionala.