Skip to content

Instantly share code, notes, and snippets.

@mox601
Created December 27, 2017 21:40
Show Gist options
  • Save mox601/89a427ff50333f7dda0b2f2e49528ec1 to your computer and use it in GitHub Desktop.
Save mox601/89a427ff50333f7dda0b2f2e49528ec1 to your computer and use it in GitHub Desktop.
Test with functional java's Reader to demonstrate Dependency Injection
package fm.mox.spikes.functionaljava;
import fj.F;
import fj.data.Reader;
import lombok.Value;
import lombok.experimental.Tolerate;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Optional;
import java.util.function.Function;
import static org.testng.Assert.assertEquals;
/**
* Created by matteo (dot) moci (at) gmail (dot) com
*/
public class ReaderTestCase {
private UserRepository userRepository;
private User bobSupervisor;
@BeforeMethod
public void setUp() throws Exception {
this.bobSupervisor = new User(2, "bob's supervisor");
this.userRepository = new UserRepository() {
@Override
public User get(int id) {
return new User(1, "Bob", bobSupervisor);
}
@Override
public User find(String username) {
if (username.equals("Bob")) {
return new User(1, "Bob", bobSupervisor);
} else {
return bobSupervisor;
}
}
};
}
// http://www.davesquared.net/2012/08/reader-monad.html
@Test
public void testR() throws Exception {
Reader<UserRepository, User> readingBobSupervisor = UserReaders
.getUser(1)
.map(User::getSupervisor)
.flatMap(user -> UserReaders.findUser(user.getUsername()));
User bobSupervisorRead = readingBobSupervisor.f(userRepository);
assertEquals(bobSupervisorRead, this.bobSupervisor);
}
//Reader for dependency injection https://www.youtube.com/watch?v=xPlsVVaMoB0&t=1659s
@Test
public void testEnv() throws Exception {
IEnv anEnvWithMockUserRepository = () -> () -> userRepository;
String oneUsername = UserService.getUsername(1).f(anEnvWithMockUserRepository);
assertEquals(oneUsername, "Bob");
}
public interface IEnv {
IRepositories repositories();
}
public static class Env {
static final Reader<IEnv, IEnv> ENV_READER =
Reader.unit((F<IEnv, IEnv>) r -> r);
static final Reader<IEnv, IRepositories> REPOSITORIES_READER =
ENV_READER.map(IEnv::repositories);
}
public interface IRepositories {
UserRepository userRepository();
}
public static class Repositories {
static final Reader<IEnv, UserRepository> USER_REPOSITORY =
Env.REPOSITORIES_READER.map(IRepositories::userRepository);
}
public static class UserRepo {
static Reader<IEnv, User> get(int id) {
return Repositories.USER_REPOSITORY.map(userRepository -> userRepository.get(id));
}
}
public static class UserService {
static Reader<IEnv, String> getUsername(int userId) {
return UserRepo.get(userId).map(User::getUsername);
}
}
public interface UserRepository {
User get(int id);
User find(String username);
}
public interface UserReaders {
static Reader<UserRepository, User> getUser(int id) {
return Reader.unit((UserRepository userRepository) -> userRepository.get(id));
}
static Reader<UserRepository, User> findUser(String username) {
return Reader.unit((UserRepository userRepository) -> userRepository.find(username));
}
static Reader<User, String> id() {
return Reader.unit(user -> user.getId() + "");
}
static Reader<User, String> username() {
return Reader.unit(User::getUsername);
}
}
@Value
private static class User {
int id;
String username;
User supervisor;
@Tolerate
private User(final int id, final String username) {
this(id, username, null);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment