gurkan
gurkan

Reputation: 529

spring boot junit mock is not returning expected value

I think it's logically correct. I mocked the classes then I wrote when-then expression but when I want to assertEquals(expected,actual) it's returning org.opentest4j.AssertionFailedError

ShortUrlServiceTest:

private ShortUrlRepository shortUrlRepository;
    private UserService userService;
    private RandomStringGenerator randomStringGenerator;
    private ShortUrlService shortUrlService;
    @BeforeEach
    public void setUp() {
        shortUrlRepository = mock(ShortUrlRepository.class);
        userService = mock(UserService.class);
        randomStringGenerator = mock(RandomStringGenerator.class);
        shortUrlService = new ShortUrlService(shortUrlRepository, userService, randomStringGenerator);
    }
    @Test
    public void testCreateWhenCodeDoesNotExistThenSave() {
        final var expected = generateShortUrl();
        when(shortUrlRepository.findByCode(expected.getCode()))
                .thenReturn(Optional.empty());
        when(userService.getUserById(expected.getUser().getId()))
                .thenReturn(expected.getUser());
        when(shortUrlRepository.save(expected))
                .thenReturn(expected);
        final var actual = shortUrlService.create(
                generateCreateShortUrlRequest(expected.getUrl(),
                        expected.getCode()),
                expected.getUser().getId()
        );
        assertEquals(expected, actual);
    }

ShortUrlService:

@Service @RequiredArgsConstructor @Slf4j
public class ShortUrlService {
    private final ShortUrlRepository repository;
    private final UserService userService;
    private final RandomStringGenerator randomStringGenerator;
    public ShortUrl create(CreateShortUrlRequest createShortUrlRequest, Long id) {
        String code = createShortUrlRequest.getCode();
        log.info("Code: " + code);

        if (code == null || code.isEmpty()) {
            code = generateCode();
            log.info("Code generated automatically: " + code);
        } else if (repository.findByCode(code).isPresent()) {
            throw new CodeAlreadyExistsException(ExceptionMessages.SHORT_URL_ALREADY_EXISTS.getValue());
        }
        log.info("Code not found in db,it's okay: " + code); // it is working

        ShortUrl shortUrl = ShortUrl.builder()
                .url(createShortUrlRequest.getUrl())
                .user(userService.getUserById(id))
                .code(code)
                .build();

        log.info("ShortUrl created: " + shortUrl); // it is working
        return repository.save(shortUrl);
    }

enter image description here

Upvotes: 0

Views: 630

Answers (1)

Johan Nordlinder
Johan Nordlinder

Reputation: 1886

Your problem is the mock for the shortUrl save method, your expected ShortUrl variable inside the mock call is not the same object to the one constructed and passed to the save method in the code being tested.

when(shortUrlRepository.save(expected)).thenReturn(expected);

Internally Mockito uses the equal() method to determine if the objects passed to a mock matchers the argument from the when() expression. If your class does not implement an equals() method the default one from Object.class is used. And this means that only the same exact same object would match, from the Java doumentation:

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

You either need to change this to:

when(shortUrlRepository.save(any())).thenReturn(expected);

Or make sure that the ShortUrl class has an properly implemented equals() method, that instead of comparing object memory references instead check if all properties match.

Upvotes: 1

Related Questions