luchob/softuni-feb2023

UnitTesting

Closed this issue · 2 comments

Здравей Лъчо,

Стигнах до един интересен казус на един от Unit тестовете, които пиша в момента.

Опитвам се да тествам този логика:

    @Override
    @Transactional
    public void removeUserFromTaskById(Long taskId,
                                       String email) {
        Optional<TaskEntity> optionalTask = this.taskRepository.findById(taskId);
        if (optionalTask.isEmpty()) {
            throw new ObjNotFoundException();
        }
        TaskEntity taskToBeUpdated = optionalTask.get();
        UserEntity userToBeRemovedFromTask = this.userService.getUserEntityByEmail(email);
        taskToBeUpdated.removeUserFromTask(userToBeRemovedFromTask);

        if (taskToBeUpdated.getCountOfAssignedUsers() == 0) {
            taskToBeUpdated.setProgress(this.progressService.getProgressEntityByType(COMPLETED));
        }
        saveTask(taskToBeUpdated);
    }

    private void saveTask(TaskEntity taskToBeUpdated) {
        this.taskRepository.saveAndFlush(taskToBeUpdated);
    }

Теста който съм написал до момента:

    @Test
    void test_removeUserFromTaskById_RemoveItSuccessfully_AndChangeProgressStatusFrom_IN_PROGRESS_to_COMPLETED() {
        long taskId = 42L;
        String email = "user@email.bg";

        UserEntity currentAssignedUser = new UserEntity().setEmail(email);
        ProgressEntity currentProgress = new ProgressEntity().setProgress(IN_PROGRESS);
        TaskEntity expectedTask = new TaskEntity()
                .setTitle("Test TITLE")
                .setProgress(currentProgress)
                .setAssignedUsers(List.of(currentAssignedUser));

        Mockito.when(this.mockTaskRepository.findById(taskId))
                .thenReturn(Optional.of(expectedTask));

        Mockito.when(this.mockUserService.getUserEntityByEmail(email))
                .thenReturn(currentAssignedUser);

        ProgressEntity newProgressCompleted = new ProgressEntity().setProgress(COMPLETED);
        Mockito.when(this.mockProgressService.getProgressEntityByType(COMPLETED))
                .thenReturn(newProgressCompleted);

        this.taskServiceToTest.removeUserFromTaskById(taskId, email);

        Mockito.verify(mockTaskRepository, Mockito.times(1))
                .saveAndFlush(taskEntityArgumentCaptor.capture());

        TaskEntity actualTask = taskEntityArgumentCaptor.getValue();
        //todo assertions
    }

Метод за премахване на юзър от списък в TaskEntity:

  public void removeUserFromTask(UserEntity userToBeDetached) {
        this.assignedUsers.remove(userToBeDetached);
    }

Случва се следното, когато кода стигне до реда на който се изпълнява :

- this.taskServiceToTest.removeUserFromTaskById(taskId, email);

И този метод влезне на ниво сървис и изпълни този код:

- taskToBeUpdated.removeUserFromTask(userToBeRemovedFromTask);

Гърми ексепшън:

 java.lang.UnsupportedOperationException

Това бих го очаквал, ако кода ми беше написан по този начин и съответно съм дал да връща Immutable collection.

 taskToBeUpdated.getAssignedUsers.remove(userToBeRemovedFromTask);

Виждам, че явно под капака на Спринг е нагласено винаги списъците да ги репрезентира, като ImmutableCollections, но се чудя как да verify промените, които са настъпили, като не мога да достигна до тези редове? Или тук единственото, което мога да нарпавя е че очаквам UnsupportedOperationException като ексепшън...? Което ми се струва, че не прави пълен теста, тъй като реално има промяна по този списък.

Дали се сещаш как бих могъл да го излъжа и да мине на следващите редове, както е очаквано?

Благодаря!

Поздрави,
Росен

luchob commented

Здравей, Роска!

Ъм... В този тест не виждам как е намесен Спринг, затова се учудвам че му гледаш под капака :) Само ти си замесен, JUnit и Mockito, няма спринг.

 TaskEntity expectedTask = new TaskEntity()
                .setTitle("Test TITLE")
                .setProgress(currentProgress)
                .setAssignedUsers(List.of(currentAssignedUser));

Това нещо е immutable -> List.of(currentAssignedUser) и мисля че затова получаваш ексепшън.

Поправи ме ако не съм разбрал нещо от въпроса.

Поздрави,
Л.

Уппс...

Написал съм Спринг, а имам предвид JUnit и Mockito...

Но да.. в действителност бях пропуснал този важен детайл, че List.of.. връща "an unmodifiable list" .

Много добре си ме разбрал! Както винаги точен :)

Благодаря за съдействието.

Поздрави,
Росен