Problem z tworzeniem obiektów w testach

0

Nawet w książce jest given when then.

Poprawiłem może teraz to lepiej wygląda chyba, że znowu przekombinowałem.

    @Test
    public void usersQuizzesWithPublicStatusCanBeFindInGlobalQuizList_test() {
        User user = newUser("test@example.com");
        User otherUser = newUser("test1@example.com");

        newQuizWithStatus("test", Status.PUBLIC, user.getEmail());
        newQuizWithStatus("test1", Status.PRIVATE, user.getEmail());
        newQuizWithStatus("test2", Status.PRIVATE, otherUser.getEmail());
        newQuizWithStatus("test3", Status.PUBLIC, otherUser.getEmail());

        List<QuizDTO> publicQuizzes = quizService.findAllPublicQuizzes();

        Assertions.assertEquals(publicQuizzes.size(), 2);
        Assertions.assertEquals(publicQuizzes.get(0).title(), "test");
        Assertions.assertEquals(publicQuizzes.get(1).title(), "test3");
    }
 @Test
    public void userShouldFindOnlyOwnQuizzes_test() {
        User user = newUser("test@example.com");
        User otherUser = newUser("test1@example.com");
        newQuizWithStatus("test", Status.PRIVATE, user.getEmail());
        newQuizWithStatus("test2", Status.PUBLIC, otherUser.getEmail());

        List<QuizDTO> userQuizzes = quizService.findYourQuizzes(new TestPrincipal(user.getEmail()));

        Assertions.assertEquals(userQuizzes.size(), 1);
        Assertions.assertEquals(userQuizzes.get(0).title(), "test");
    }
0
LukaszCh233 napisał(a):

Nawet w książce jest given when then.

Given, when, then to jest praktyka wywodząca się z BDD. Jest pomocna jeśli stosuje się ją poprawnie; ale nic nie daje jeśli używa się jej jako takie "odgraniczniki w kodzie".

I uwierz mi, 90% użyć tego jest niepoprawne.

LukaszCh233 napisał(a):

Poprawiłem może teraz to lepiej wygląda chyba, że znowu przekombinowałem.

W usersQuizzesWithPublicStatusCanBeFindInGlobalQuizList_test użytkownicy są niepotrzebni, i 4 quizy też są niepotrzebne, wystarczyłyby dwa:

@Test
public void usersQuizzesWithPublicStatusCanBeFindInGlobalQuizList_test() {
    newQuizWithStatus("quiz", Status.PUBLIC);
    newQuizWithStatus("secret", Status.PRIVATE);

    List<QuizDTO> quizes = quizService.findAllPublicQuizzes();

    Assertions.assertEquals(publicQuizzes.size(), 1);
    Assertions.assertEquals(publicQuizzes.get(0).title(), "quiz");
}

userShouldFindOnlyOwnQuizzes_test jest dobry! Gratuluję! Bardzo fajny test. Jednak nadal można go poprawić. Zamiast user.getEmail() lepiej by było wpisać mail, "test@example.com":

@Test
public void userShouldFindOnlyOwnQuizzes_test() {
    newUser("user@example.com");
    newUser("other@example.com");
    newQuizWithStatus("mine", Status.PRIVATE, "user@example.com");
    newQuizWithStatus("someone's", Status.PUBLIC, "other@example.com");

    List<QuizDTO> userQuizzes = quizService.findYourQuizzes(new TestPrincipal("user@example.com"));

    Assertions.assertEquals(userQuizzes.size(), 1);
    Assertions.assertEquals(userQuizzes.get(0).title(), "mine");
}
0
Riddle napisał(a):
LukaszCh233 napisał(a):

W usersQuizzesWithPublicStatusCanBeFindInGlobalQuizList_test użytkownicy są niepotrzebni, i 4 quizy też są niepotrzebne, wystarczyłyby dwa:

Chciałem pokazać, że 2 inni użytkownicy dodają quiz z statusem public i widać je globalnie

userShouldFindOnlyOwnQuizzes_test jest dobry! Gratuluję! Bardzo fajny test. Jednak nadal można go poprawić. Zamiast user.getEmail() lepiej by było wpisać mail, "test@example.com":

Masz rację poprawione już.

Tu jeszcze jeden ale nie jestem pewny co do niego

 @Test
    public void userCanDeleteOnlyOwnQuizzes_test() {
        newUser("test@example.com");
        newUser("test1@example.com");

        newQuiz("test", "test@example.com");
        newQuiz("test1", "test1@example.com");

        quizService.deleteAllQuizzesForUser(new TestPrincipal("test@example.com"));

        List<Quiz> quizList = quizRepository.findAll();

        Assertions.assertEquals(quizList.size(), 1);
        Assertions.assertEquals(quizList.get(0).getTitle(), "test1");
    }
0
LukaszCh233 napisał(a):

Chciałem pokazać, że 2 inni użytkownicy dodają quiz z statusem public i widać je globalnie

No to należało pod to napisać osobny test, jeśli tego potrzebujesz; a nie komplikować istniejący.

LukaszCh233 napisał(a):

Tu jeszcze jeden ale nie jestem pewny co do niego
}

No, quiz nazywa się userCanDeleteOnlyOwnQuizzes_test a test widzę że testuje usuwanie quizów użytkownika (nie ważne jakiego). To jak to w końcu jest?

Chcąc napisać test że samemu się usuwa swoje rzeczy, to powinno być tak:

@Test
public void userCanDeleteOnlyOwnQuizes() {
    loggedInAs("test@example.com");
    newQuiz("mine", "test@example.com");
    newQuiz("someone's", "someone@example.com");

    deleteOwnQuizes();

    List<Quiz> quizList = quizRepository.findAll();
    Assertions.assertEquals(quizList.size(), 1);
    Assertions.assertEquals(quizList.get(0).getTitle(), "someone's");
}
0

No, quiz nazywa się userCanDeleteOnlyOwnQuizzes_test a test widzę że testuje usuwanie quizów użytkownika (nie ważne jakiego). To jak to w końcu jest?

Tak myślałem, że coś jest nie tak.
Czy teraz dobrze?

   @Test
    public void userCanDeleteOnlyOwnQuizzes_test() {
        newUser("user@example.com");
        newUser("other@example.com");

        newQuiz("mine", "user@example.com");
        newQuiz("someone", "other@example.com");

        deleteOwnQuizzes();

        List<Quiz> quizList = quizRepository.findAll();

        Assertions.assertEquals(quizList.size(), 1);
        Assertions.assertEquals(quizList.get(0).getTitle(), "someone");
    }

 private void deleteOwnQuizzes() {
        quizService.deleteAllQuizzesForUser(new TestPrincipal("user@example.com"));
    }

@Test
    public void quizzesWithPublicStatusCanBeFindInGlobalQuizList_test() {

        newQuizWithStatus("quiz", Status.PUBLIC);
        newQuizWithStatus("secret", Status.PRIVATE);

        List<QuizDTO> publicQuizzes = quizService.findAllPublicQuizzes();

        Assertions.assertEquals(publicQuizzes.size(), 1);
        Assertions.assertEquals(publicQuizzes.get(0).title(), "quiz");
    }

    @Test
    public void userShouldFindOnlyOwnQuizzes_test() {
        newUser("user@example.com");
        newUser("other@example.com");

        newQuiz("mine", "user@example.com");
        newQuiz("someone", "other@example.com");

        List<QuizDTO> userQuizzes = quizService.findYourQuizzes(new TestPrincipal("user@example.com"));

        Assertions.assertEquals(userQuizzes.size(), 1);
        Assertions.assertEquals(userQuizzes.get(0).title(), "mine");
    }

    @Test
    public void quizInCategoryCanBeFindByThatCategory_test() {
        QuizCategory quizCategory = new QuizCategory(null, "testCategory");
        quizCategoryService.createQuizCategory(quizCategory);

        newQuizWithCategory("test", quizCategory);

        List<QuizDTO> quizzesInCategory = quizService.findQuizByCategory(quizCategory.getId());

        Assertions.assertEquals(quizzesInCategory.get(0).title(), "test");
    }

private void newQuizWithStatus(String title, Status status) {

        QuizCategory quizCategory = new QuizCategory(null, "TestCategory");
        quizCategoryRepository.save(quizCategory);

        Quiz quiz = new Quiz();
        quiz.setTitle(title);
        quiz.setUserId(null);
        quiz.setQuizCategory(quizCategory);
        quiz.setStatus(status);
        quizRepository.save(quiz);
    }

private void newUser(String email) {
        User user = new User(null, "testName", email, "password", Role.USER);
        userRepository.save(user);
    }

 private void newQuizWithCategory(String title, QuizCategory quizCategory) {
        Quiz quiz = new Quiz();
        quiz.setTitle(title);
        quiz.setUserId(1L);
        quiz.setQuizCategory(quizCategory);
        quiz.setStatus(Status.PUBLIC);
        quizRepository.save(quiz);
    }

    private void newQuiz(String title, String email) {
        QuizCategory quizCategory = new QuizCategory(null, "TestCategory");
        quizCategoryRepository.save(quizCategory);

        Quiz quiz = new Quiz();
        quiz.setTitle(title);
        quiz.setUserId(null);
        quiz.setQuizCategory(quizCategory);
        quiz.setStatus(Status.PUBLIC);
        quizService.createQuiz(quiz.getTitle(), quizCategory.getId(), quiz.getStatus(), new TestPrincipal(email
        ));
    }

    private void deleteOwnQuizzes() {
        quizService.deleteAllQuizzesForUser(new TestPrincipal("user@example.com"));
    }
0

Lepiej.

newUser("user@example.com"); // te linijki są niepotrzebne
newUser("other@example.com"); // te linijki są niepotrzebne

newQuiz("mine", "user@example.com");
newQuiz("someone", "other@example.com");

quizInCategoryCanBeFindByThatCategory_test() nic nie testuje. Jeśli w findQuizByCategory() zrobię po prostu return findAll() to ten test przejdzie.

0
Riddle napisał(a):

Lepiej.

newUser("user@example.com"); // te linijki są niepotrzebne
newUser("other@example.com"); // te linijki są niepotrzebne

newQuiz("mine", "user@example.com");
newQuiz("someone", "other@example.com");

quizInCategoryCanBeFindByThatCategory_test() nic nie testuje. Jeśli w findQuizByCategory() zrobię po prostu return findAll() to ten test przejdzie.

W newQuiz() mam quizService.createQuiz(quiz.getTitle(), quizCategory.getId(), quiz.getStatus(), new TestPrincipal(email
));
wiec są potrzebne, chyba, że zmienie na po prostu quizRepository.save w tedy juz nie będą potrzebne

0

Możesz stworzyć usera w newQuiz(). Nie ma potrzeby żeby ta linijka była w teście, może być w metodzie pomocniczej.

1

Nowy test wydaje mi sie dobry i nie przechodzi jesli są zmieniane odpowiedzi ma błędne.

@Test
    public void whenSolveQuizCorrectResultShouldBeMax_test() {
        Quiz quiz = newQuizWithQuestions("mine", "user@example.com");

        List<UserAnswer> userAnswers = new ArrayList<>();
        UserAnswer answer1 = new UserAnswer(1L);
        UserAnswer answer2 = new UserAnswer(1L);
        userAnswers.add(answer1);
        userAnswers.add(answer2);

        double score = quizService.solveQuiz(quiz.getId(), userAnswers, new TestPrincipal("user@example.com"));

        Assertions.assertEquals(score, 100.0);
    }

@Test
    public void userShouldFindOnlyOwnQuizResults_test() {
        newResult(50.0,"user@example.com");
        
        List<QuizResultDTO> quizResults = quizResultService.findYourQuizzesResults(new TestPrincipal("user@example.com"));

        Assertions.assertEquals(quizResults.size(),1);
        Assertions.assertEquals(quizResults.get(0).score(),50.0);
    }

private void newResult(double score, String email) {
        User user = new User(null, "testName", email, "password", Role.USER);
        userRepository.save(user);

        QuizCategory quizCategory = new QuizCategory(null, "TestCategory");
        quizCategoryRepository.save(quizCategory);

        Quiz quiz = new Quiz();
        quiz.setTitle("title");
        quiz.setUserId(user.getId());
        quiz.setQuizCategory(quizCategory);
        quiz.setStatus(Status.PUBLIC);
        quizRepository.save(quiz);

        Result result = new Result();
        result.setUser(user);
        result.setQuiz(quiz);
        result.setScore(score);

        resultRepository.save(result);
    }


   private Quiz newQuizWithQuestions(String title, String email) {
        User user = new User(null, "testName", email, "password", Role.USER);
        userRepository.save(user);
        QuizCategory quizCategory = new QuizCategory(null, "TestCategory");
        quizCategoryRepository.save(quizCategory);

        Quiz quiz = new Quiz();
        quiz.setTitle(title);
        quiz.setUserId(user.getId());
        quiz.setQuizCategory(quizCategory);
        quiz.setStatus(Status.PUBLIC);
        quiz.setQuestions(new ArrayList<>());
        quiz = quizRepository.save(quiz); // Save quiz and get the managed instance

        List<Question> questions = new ArrayList<>();

        questions.add(addQuestionsToQuiz(1L, "test", quiz));
        questions.add(addQuestionsToQuiz(2L, "test1", quiz));
        quiz.setQuestions(questions);

        return quizRepository.save(quiz);
    }

    private Question addQuestionsToQuiz(Long number, String content, Quiz quiz) {
        List<AnswerToQuiz> answerToQuizList = new ArrayList<>();
        AnswerToQuiz answerToQuiz1 = new AnswerToQuiz();
        answerToQuiz1.setAnswerNumber(1L);
        answerToQuiz1.setContent("a");
        answerToQuiz1.setCorrect(true);

        AnswerToQuiz answerToQuiz2 = new AnswerToQuiz();
        answerToQuiz2.setAnswerNumber(2L);
        answerToQuiz2.setContent("b");
        answerToQuiz2.setCorrect(false);

        answerToQuizList.add(answerToQuiz1);
        answerToQuizList.add(answerToQuiz2);

        Question question = new Question();
        question.setQuiz(quiz);
        question.setContent(content);
        question.setQuestionNumber(number);
        question.setAnswerToQuiz(answerToQuizList);

        answerToQuiz1.setQuestion(question);
        answerToQuiz2.setQuestion(question);

        return quizQuestionRepository.save(question);
    }
0

Hej mam problem z testem jednym. W metodzie solve mam mieszanie słówek, żeby były różne kolejności no i przez to wynik nie zawsze bedzie taki sam. W programie chyba też nie przejdzie te mieszanie bez fornta bo nie widać tych słówek tylko podaje całego jsona.

@Test
    public void scoreShouldBeMaxWhenSolveWordSetCorrect() {
        WordSet wordSet = newWordSetWithWords("user@example.com");
        List<AnswerToWordSet> userAnswers = new ArrayList<>();
        AnswerToWordSet answerToWordSet1 = new AnswerToWordSet("translate1");
        AnswerToWordSet answerToWordSet2 = new AnswerToWordSet("translate2");
        userAnswers.add(answerToWordSet1);
        userAnswers.add(answerToWordSet2);

        double score = wordSetService.solveWordSet(wordSet.getId(), userAnswers, new TestPrincipal("user@example.com"));

        Assertions.assertEquals(score, 100.0);
    }

private WordSet newWordSetWithWords(String email) {
        User user = new User(null, "testName", email, "password", Role.USER);
        userRepository.save(user);
        WordSetCategory wordSetCategory = new WordSetCategory(null, "TestCategory");
        wordSetCategoryRepository.save(wordSetCategory);

        WordSet wordSet = new WordSet();
        wordSet.setWordSetCategory(wordSetCategory);
        wordSet.setTitle("title");
        wordSet.setUserId(1L);
        wordSet.setWords(new ArrayList<>());
        wordSet.setStatus(Status.PUBLIC);
        wordSetRepository.save(wordSet);

        List<Word> wordList = new ArrayList<>();
        wordList.add(new Word(null, 1L, "word1", "translate1", wordSet));
        wordList.add(new Word(null, 2L, "word2", "translate2", wordSet));
        wordSet.setWords(wordList);

        return wordSetRepository.save(wordSet);
    }

public double solveWordSet(Long wordSetId, List<AnswerToWordSet> userAnswers, Principal principal) {
        String email = principal.getName();
        User user = userRepository.findByEmail(email).orElseThrow(() -> new EntityNotFoundException("Not found user"));

        WordSet wordSet = wordSetRepository.findById(wordSetId).orElseThrow(() -> new EntityNotFoundException("Word set not found"));
        Result prviousResult = resultRepository.findByUserIdAndWordSetId(user.getId(), wordSetId);

        List<Word> words = new ArrayList<>(wordSet.getWords());

        Collections.shuffle(words);

        int point = 0;

        if (userAnswers.size() != words.size()) {
            throw new IllegalArgumentException("Number of user answers does not match the number of words in the set");
        }
        for (int i = 0; i < words.size(); i++) {
            Word word = words.get(i);
            AnswerToWordSet userAnswer = userAnswers.get(i);

            if (word.getTranslation().equalsIgnoreCase(userAnswer.getAnswer())) {
                point++;
            }
        }
        double score = (double) point / wordSet.getWords().size() * 100;
        if (prviousResult == null || score > prviousResult.getScore()) {

            Result result = new Result();
            result.setUser(user);
            result.setScore(score);
            result.setWordSet(wordSet);
            resultRepository.save(result);
        }
        if (prviousResult != null && score > prviousResult.getScore()) {
            resultRepository.delete(prviousResult);
        }
        return score;
    }
0
LukaszCh233 napisał(a):

W metodzie solve mam mieszanie słówek, żeby były różne kolejności no i przez to wynik nie zawsze bedzie taki sam. W programie chyba też nie przejdzie te mieszanie bez fornta bo nie widać tych słówek tylko podaje całego jsona.

Nie rozumiem co próbujesz zrobić 😕 Mógłbyś lepiej opisać Twój spodziewany efekt?

0
Riddle napisał(a):
LukaszCh233 napisał(a):

W metodzie solve mam mieszanie słówek, żeby były różne kolejności no i przez to wynik nie zawsze bedzie taki sam. W programie chyba też nie przejdzie te mieszanie bez fornta bo nie widać tych słówek tylko podaje całego jsona.

Nie rozumiem co próbujesz zrobić 😕 Mógłbyś lepiej opisać Twój spodziewany efekt?

No mam metodę solveWordSet i w niej mam Collections.shuffle(words) żeby zestaw słówek miał różną kolejność za każdym razem.
Problem w tym, że jak używam postmana do poruszania sie po projekcie to nie widzę jak wygląda kolejność tych słówek po zmieszaniu wiec nie moge podać dobrych odpowiedzi. Tak samo w tym teście przez to, że mieszam słówka to nie pokrywają się zawsze z odpowiedziami i przez to test raz przejdzie raz nie.

0

Twój program jest niedeterministyczny. Sam to zauważyłeś - testy raz przechodzą, a raz nie.

  Collections.shuffle(words);

Użyj:

  Collections.shuffle(words, new Random(<tutaj jakiś stały seed>));

albo nawet lepiej - jakiegoś innego patternu zwracania predeterminowanych wartości losowych w testach, bo new Random() używa prawdziwego PRNG i będzie to dość upierdliwe w użyciu.
Aczkolwiek będzie wymagało to przerobienia kodu, żeby dało się wstrzyknąć źródło (pseudo)losowości.

0

@kelog: a czy ten problem był by też jak by był do tego frontend? Wtedy użytkownik widzi do jakiego słowa ma podać odpowiedź bo mu się wyświetla. Tak z ciekawości pytam.

0

Hej mam problem czy jest ktoś w stanie powiedzieć mi co robię źle? Bo tak patrzę i nie widzę. Update działa normalnie w aplikacji jak sprawdzam postmanem a w teście już nie chce aktualizować.

Mam test:

@Test
public void whenUpdateBasketProductQuantityPriceShouldBeUpdate_test() {
    Customer customer = newCustomer("customer@example.com");
    Basket basket = newBasket(10L, 10.0, customer);

    Basket updateQuantity = basketService.updateBasketProductQuantity(basket.getBasketProducts().get(0).getId(), 5L, new TestPrincipal("customer@example.com"));

    Assertions.assertEquals(5, updateQuantity.getBasketProducts().get(0).getQuantity());
    Assertions.assertEquals(50, updateQuantity.getTotalPrice());
}
org.opentest4j.AssertionFailedError: 
Expected :5
Actual   :10

private Basket newBasket(Long quantity, double price, Customer customer) {
    Category category = new Category(null, "category");
    categoryRepository.save(category);

    Book book = new Book();
    book.setCategory(category);
    book.setTitle("title");
    book.setAuthor("test");
    book.setPrice(price);
    book.setQuantity(100L);
    book.setStatus(Status.AVAILABLE);
    bookRepository.save(book);

    Basket basket = new Basket();
    basket.setUserId(customer.getId());
    basket.setBasketProducts(new ArrayList<>());
    basketRepository.save(basket);

    BasketProducts basketProducts = new BasketProducts();
    basketProducts.setName(book.getTitle());
    basketProducts.setBasket(basket);
    basketProducts.setAuthor(book.getAuthor());
    basketProducts.setPrice(book.getPrice());
    basketProducts.setIdBook(book.getId());
    basketProducts.setQuantity(quantity);

    basket.getBasketProducts().add(basketProducts);
    basket.setTotalPrice(basketProducts.getPrice() * quantity);

    return basketRepository.save(basket);
}

Tu metoda:

public Basket updateBasketProductQuantity(Long productId, Long quantity, Principal principal) {
    Basket basket = findBasketByUserPrincipal(principal);

    BasketProducts basketProduct = Optional.ofNullable(basketProductsRepository.findBasketProductById(productId))
            .orElseThrow(() -> new EntityNotFoundException("Book not found"));

    Book selectedBook = bookRepository.findById(basketProduct.getIdBook())
            .orElseThrow(() -> new EntityNotFoundException("Not found Book"));

    if (selectedBook.getQuantity() < quantity) {
        throw new NotEnoughBooksException("There are not enough books available");
    }
    basketProduct.setQuantity(quantity);

    basket.updateTotalPrice(basket);
    
    if (basketProduct.getQuantity() <= 0) {
        basketProductsRepository.deleteById(basketProduct.getId());
    }

    return basketRepository.save(basket);
}
0
LukaszCh233 napisał(a):

Hej mam problem czy jest ktoś w stanie powiedzieć mi co robię źle? Bo tak patrzę i nie widzę. Update działa normalnie w aplikacji jak sprawdzam postmanem a w teście już nie chce aktualizować.

Czytam test whenUpdateBasketProductQuantityPriceShouldBeUpdate_test(), i szczerze mówiąc, po nim nie widać co on dokładnie testuje 😐 Nie mam pojęcia co on ma sprawdzać.

0
Riddle napisał(a):
LukaszCh233 napisał(a):

Hej mam problem czy jest ktoś w stanie powiedzieć mi co robię źle? Bo tak patrzę i nie widzę. Update działa normalnie w aplikacji jak sprawdzam postmanem a w teście już nie chce aktualizować.

Czytam test whenUpdateBasketProductQuantityPriceShouldBeUpdate_test(), i szczerze mówiąc, po nim nie widać co on dokładnie testuje 😐 Nie mam pojęcia co on ma sprawdzać.

No jak mam coś w koszyku i chce zmienić ilość książek to po udpate zmienia sie total price, taki jest zamysł testu 😅

To dodam od razu inne testy:

@Test
    public void shouldDisplayBasketWithYourBooksWhenAddBookToBasket_test() {
        newCustomer("customer@example.com");
        Book book = newBook("title");

        basketService.addBookToBasket(book.getId(), 1L, new TestPrincipal("customer@example.com"));

        BasketDTO basket = basketService.findBasketDTOByUserPrincipal(new TestPrincipal("customer@example.com"));

        Assertions.assertEquals(basket.basketProductsList().get(0).name(), "title");
    }

 @Test
    public void whenFindBookByTitleCanFindSimilarBooksTitle_test() {
        newBook("testBook");
        newBook("otherBook");

        List<Book> bookList = bookService.findByTitle("Book");

        Assertions.assertEquals(bookList.size(), 2);
        Assertions.assertEquals(bookList.get(0).getTitle(), "testBook");
        Assertions.assertEquals(bookList.get(1).getTitle(), "otherBook");
    }

    @Test
    public void shouldFindBookByCategoryName_test() {
        Category category = new Category(null, "category");
        categoryRepository.save(category);
        newBookWithCategory("book", category);

        List<Book> bookList = bookService.findByCategoryName("category");

        Assertions.assertEquals(bookList.size(), 1);
        Assertions.assertEquals(bookList.get(0).getTitle(), "book");
    }
0

W metodzie updateBasketProductQuantity wołasz kilkukrotnie różne metody na bookRepository czy basketProductsRepository.
Nie pokazałeś całej klasy testów więc nie wiadomo co i gdzie zadeklarowałeś z mocka (chyba, że zrobiłeś implementację repository inMemory).

Strzelam, że gdzieś w tej klasie testowej masz zadeklarowane, że basketRepository to mock a metoda save() ma zwrócić basket stworzony z wartością 10 (tak jak mówi test).

Jeżeli bazujesz na mockowaniu tych repozytoriów to tego typu testy nie mają większego sensu gdy wynikiem działania metody jest to co zwraca mock (wtedy testuje sie to integracyjnie z odpaleniem prawdziwej bazy h2 czy innej w np. test containers).

0
RequiredNickname napisał(a):

W metodzie updateBasketProductQuantity wołasz kilkukrotnie różne metody na bookRepository czy basketProductsRepository.
Nie pokazałeś całej klasy testów więc nie wiadomo co i gdzie zadeklarowałeś z mocka (chyba, że zrobiłeś implementację repository inMemory).

Strzelam, że gdzieś w tej klasie testowej masz zadeklarowane, że basketRepository to mock a metoda save() ma zwrócić basket stworzony z wartością 10 (tak jak mówi test).

Jeżeli bazujesz na mockowaniu tych repozytoriów to tego typu testy nie mają większego sensu gdy wynikiem działania metody jest to co zwraca mock (wtedy testuje sie to integracyjnie z odpaleniem prawdziwej bazy h2 czy innej w np. test containers).

Ale te testy są robione na bazie h2 nie ma żadnych mockow

0

Wrzuć to na jakiegoś githuba bo to trochę wróżenie z fusów.Możesz sobie odpalić test w trybie debuggera i normalnie w kodzie breakpointa postawić i prześledzić linijka po linijce.

0
RequiredNickname napisał(a):

Wrzuć to na jakiegoś githuba bo to trochę wróżenie z fusów.Możesz sobie odpalić test w trybie debuggera i normalnie w kodzie breakpointa postawić i prześledzić linijka po linijce.

https://github.com/LukaszCh233/Books_store
Prosze bardzo dodane

0

Test zaczął działać po dodaniu @Transacional
Nie bardzo rozumiem czemu tak trzeba zrobić.
Czy to przez to, że prócz quentity zmieniane jest też totalPrice czy jak?
Zmiany są wprowadzane w tabeli basket i powiązanej z nią basketProducts co musi być spójne dlatego ta adnotacja tak to rozumiem.
Tylko czemu w metodzie nie jest potrzebna a w testach już potrzebna?

0

Ja sklonowałem repo i na branchu main nie masz w testach @Transactional a mimo to mi testy wszędzie przechodzą.
@Transactional w testach ludzie używają aby po zakończeniu testów transakcxja była wycofywana i aby "wyczyścić" db.

Co do Twoich testów to:

  1. po co Ci sufix "_test" w nazwach testów? Zupełnie zbedne, przecież wiadomo, że to metoda testowa.
  2. Zamiast robić same testy integrtacyjne warto byłoby zrobić unit testy (chociaż w crudzie ciężko bo ze świecą szukać logiki którą warto byłoby testować) gdzie np. i/o zaimplementowałbyś inMemory
  3. testujesz tylko happy path bez różnych wartości, przypadków brzegowych czy obsługi wyjątków
0
RequiredNickname napisał(a):

Ja sklonowałem repo i na branchu main nie masz w testach @Transactional a mimo to mi testy wszędzie przechodzą.
@Transactional w testach ludzie używają aby po zakończeniu testów transakcxja była wycofywana i aby "wyczyścić" db.

Co do Twoich testów to:

  1. po co Ci sufix "_test" w nazwach testów? Zupełnie zbedne, przecież wiadomo, że to metoda testowa.
  2. Zamiast robić same testy integrtacyjne warto byłoby zrobić unit testy (chociaż w crudzie ciężko bo ze świecą szukać logiki którą warto byłoby testować) gdzie np. i/o zaimplementowałbyś inMemory
  3. testujesz tylko happy path bez różnych wartości, przypadków brzegowych czy obsługi

Bo transactional dodałem po commicie, to nie wiem czemu tak jest ale przechodzą z powodzeniem? Mi właśnie ten jeden test z updateQuentity nie aktualizuje liczby bez transactional.

0

Wcześniej przechodziłī a teraz przestały.
Problem najpewniej leży w izolacji testów i tego, że baza nie jest poprawnie czyszczona przed każdym testem (dlatego @Transactional pomagał).

Nie używaj w testach na potęgę wszędzie tych samych stałych literałów bo to też może prowadzić do problemów.

0

@RequiredNickname: to zostawić ten transactional w tym teście czy szukać innego rozwiązania? Bo on nawet nie aktualizuje quantity kiedy jest uruchamiany osobno.
Jak daje transactional przy metodzie w service zamaist w tescie też test przechodzi i działa

0

Co do @Transactional w musisz się zastanowić czy potrzebujesz tam aby Spring spiał wiele operacji w jedną transakcję.
Co do @Transactional w teście to pewnie da się to ograć w mniej "magiczny" sposób poprzez unikanie stałych literałów i czyszczenie bazy danych PRZED każdym testem.
Jako, że to projekt stricte rozwojowy to przemyśl sobie czy aby na pewno chcesz w każdym teście podnosić kontekst springa i testować w oparciu o bazę danych (choćby h2 inMemory)?
Tak jak pisałem, możesz pójść w stronę unit testów bez podnoszenia kontekstu springa z implementacją bazy w pamięci (często hashMapa) aby testy były dużooooo szybsze.
Ogólnie poczytaj o piramidzie testów... potem o tym, że nie zawsze sztywne trzymanie się jej jest odpowiednie, poczytaj o testowaniu modułów bardziej blackboxowo (testując zachowanie aniżeli implementację aczkolwiek ta uwaga nie jest spowodowana tym, że rzuciło mi się to u Ciebie w projekcie w oczy, to tylko wzmianka abyś o tym poczytał).

Na koniec poucz się o:

  • izolacji testów (Twoje ewidentnie mają z tym problem skoro raz przechodzą a raz nie)
  • rozajach testów (unit testy, testy integracyjne, testy end-2-end itp)
  • podejściu do stosowania mocków (szkołą londyńska vs detroit)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.