/* * Copyright (c) 2024, Antonio Gabriel Muñoz Conejo <me at tonivade dot es> * Distributed under the terms of the MIT License */ package com.github.tonivade.vavr.effect; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import io.vavr.CheckedConsumer; import io.vavr.Tuple2; @ExtendWith(MockitoExtension.class) class ResourceTest { private <T extends AutoCloseable> Resource<T> makeResource(IO<T> acquire) { return makeResource(acquire, AutoCloseable::close); } private <T> Resource<T> makeResource(IO<T> acquire, CheckedConsumer<T> release) { return Resource.from(acquire, release); } @Test void use(@Mock CheckedConsumer<String> release) throws Throwable { Resource<String> resource = makeResource(IO.pure("hola"), release); IO<String> use = resource.use(string -> IO.pure(string.toUpperCase())); assertEquals("HOLA", use.unsafeRunSync()); verify(release).accept("hola"); } @Test void map(@Mock CheckedConsumer<String> release) throws Throwable { Resource<String> resource = makeResource(IO.pure("hola"), release).map(String::toUpperCase); IO<Integer> use = resource.use(string -> IO.pure(string.length())); assertEquals(4, use.unsafeRunSync()); verify(release).accept("hola"); } @Test void flatMap(@Mock DataSource dataSource, @Mock Connection connection, @Mock PreparedStatement statement, @Mock ResultSet resultSet) throws SQLException { when(dataSource.getConnection()).thenReturn(connection); when(connection.prepareStatement("sql")).thenReturn(statement); when(statement.executeQuery()).thenReturn(resultSet); when(resultSet.getString(0)).thenReturn("result"); Resource<ResultSet> flatMap = makeResource(IO.task(dataSource::getConnection)) .flatMap(conn -> makeResource(IO.task(() -> conn.prepareStatement("sql")))) .flatMap(stmt -> makeResource(IO.task(() -> stmt.executeQuery()))); IO<String> use = flatMap.use(rs -> IO.task(() -> rs.getString(0))); assertEquals("result", use.unsafeRunSync()); InOrder inOrder = inOrder(resultSet, statement, connection); inOrder.verify(resultSet).close(); inOrder.verify(statement).close(); inOrder.verify(connection).close(); } @Test void combine(@Mock CheckedConsumer<String> release1, @Mock CheckedConsumer<Integer> release2) throws Throwable { Resource<String> res1 = makeResource(IO.pure("hola"), release1); Resource<Integer> res2 = makeResource(IO.pure(5), release2); Resource<Tuple2<String, Integer>> combine = res1.combine(res2); IO<String> use = combine.use(tuple -> IO.task(tuple::toString)); assertEquals("(hola, 5)", use.unsafeRunSync()); verify(release1).accept("hola"); verify(release2).accept(5); } }