MATCHER = new ModelMatcher<>(
+ (expected, actual) -> expected == actual ||
+ (Objects.equals(expected.getPassword(), actual.getPassword())
+ && Objects.equals(expected.getId(), actual.getId())
+ && Objects.equals(expected.getName(), actual.getName())
+ && Objects.equals(expected.getEmail(), actual.getEmail())
+ && Objects.equals(expected.getCaloriesPerDay(), actual.getCaloriesPerDay())
+ && Objects.equals(expected.isEnabled(), actual.isEnabled())
+// && Objects.equals(expected.getRoles(), actual.getRoles())
+ )
+ );
+}
\ No newline at end of file
diff --git a/src/test/java/ru/javawebinar/topjava/matcher/ModelMatcher.java b/src/test/java/ru/javawebinar/topjava/matcher/ModelMatcher.java
new file mode 100644
index 000000000000..052c69ce5b2e
--- /dev/null
+++ b/src/test/java/ru/javawebinar/topjava/matcher/ModelMatcher.java
@@ -0,0 +1,72 @@
+package ru.javawebinar.topjava.matcher;
+
+import org.junit.Assert;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * GKislin
+ * 06.01.2015.
+ *
+ * This class wrap every entity by Wrapper before assertEquals in order to compare them by comparator
+ * Default comparator compare by String.valueOf(entity)
+ *
+ * @param : Entity
+ */
+public class ModelMatcher {
+ public interface Comparator {
+ boolean compare(T expected, T actual);
+ }
+
+ private static final Comparator DEFAULT_COMPARATOR =
+ (Object expected, Object actual) -> expected == actual || String.valueOf(expected).equals(String.valueOf(actual));
+
+ private Comparator comparator;
+
+ public ModelMatcher() {
+ this((Comparator) DEFAULT_COMPARATOR);
+ }
+
+ public ModelMatcher(Comparator comparator) {
+ this.comparator = comparator;
+ }
+
+ private class Wrapper {
+ private T entity;
+
+ private Wrapper(T entity) {
+ this.entity = entity;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Wrapper that = (Wrapper) o;
+ return entity != null ? comparator.compare(entity, that.entity) : that.entity == null;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(entity);
+ }
+ }
+
+ public void assertEquals(T expected, T actual) {
+ Assert.assertEquals(wrap(expected), wrap(actual));
+ }
+
+ public void assertCollectionEquals(Collection expected, Collection actual) {
+ Assert.assertEquals(wrap(expected), wrap(actual));
+ }
+
+ public Wrapper wrap(T entity) {
+ return new Wrapper(entity);
+ }
+
+ public List wrap(Collection collection) {
+ return collection.stream().map(this::wrap).collect(Collectors.toList());
+ }
+}
diff --git a/src/test/java/ru/javawebinar/topjava/repository/mock/InMemoryMealRepositoryImpl.java b/src/test/java/ru/javawebinar/topjava/repository/mock/InMemoryMealRepositoryImpl.java
new file mode 100644
index 000000000000..6a644f9fe054
--- /dev/null
+++ b/src/test/java/ru/javawebinar/topjava/repository/mock/InMemoryMealRepositoryImpl.java
@@ -0,0 +1,79 @@
+package ru.javawebinar.topjava.repository.mock;
+
+import org.springframework.stereotype.Repository;
+import ru.javawebinar.topjava.model.Meal;
+import ru.javawebinar.topjava.repository.MealRepository;
+import ru.javawebinar.topjava.util.TimeUtil;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * GKislin
+ * 15.09.2015.
+ */
+@Repository
+public class InMemoryMealRepositoryImpl implements MealRepository {
+
+ private static final Comparator MEAL_COMPARATOR = Comparator.comparing(Meal::getDateTime).reversed();
+
+ // Map userId -> (mealId-> meal)
+ private Map> repository = new ConcurrentHashMap<>();
+ private AtomicInteger counter = new AtomicInteger(0);
+
+ @Override
+ public Meal save(Meal meal, int userId) {
+ Objects.requireNonNull(meal);
+
+ Integer mealId = meal.getId();
+ if (meal.isNew()) {
+ mealId = counter.incrementAndGet();
+ meal.setId(mealId);
+ } else if (get(mealId, userId) == null) {
+ return null;
+ }
+ Map meals = repository.computeIfAbsent(userId, ConcurrentHashMap::new);
+ meals.put(mealId, meal);
+ return meal;
+ }
+
+ @Override
+ public boolean delete(int id, int userId) {
+ Map meals = repository.get(userId);
+ return meals != null && meals.remove(id) != null;
+ }
+
+ @Override
+ public Meal get(int id, int userId) {
+ Map meals = repository.get(userId);
+ return meals == null ? null : meals.get(id);
+ }
+
+ @Override
+ public Collection getAll(int userId) {
+ return getAllStream(userId).collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection getBetween(LocalDateTime startDateTime, LocalDateTime endDateTime, int userId) {
+ Objects.requireNonNull(startDateTime);
+ Objects.requireNonNull(endDateTime);
+ return getAllStream(userId)
+ .filter(um -> TimeUtil.isBetween(um.getDateTime(), startDateTime, endDateTime))
+ .collect(Collectors.toList());
+ }
+
+ private Stream getAllStream(int userId) {
+ Map meals = repository.get(userId);
+ return meals == null ?
+ Stream.empty() : meals.values().stream().sorted(MEAL_COMPARATOR);
+ }
+}
+
diff --git a/src/test/java/ru/javawebinar/topjava/repository/mock/InMemoryUserRepositoryImpl.java b/src/test/java/ru/javawebinar/topjava/repository/mock/InMemoryUserRepositoryImpl.java
new file mode 100644
index 000000000000..6b1e658d5739
--- /dev/null
+++ b/src/test/java/ru/javawebinar/topjava/repository/mock/InMemoryUserRepositoryImpl.java
@@ -0,0 +1,77 @@
+package ru.javawebinar.topjava.repository.mock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Repository;
+import ru.javawebinar.topjava.model.User;
+import ru.javawebinar.topjava.repository.UserRepository;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * GKislin
+ * 15.06.2015.
+ */
+@Repository
+public class InMemoryUserRepositoryImpl implements UserRepository {
+ private static final Logger LOG = LoggerFactory.getLogger(InMemoryUserRepositoryImpl.class);
+
+ private Map repository = new ConcurrentHashMap<>();
+ private AtomicInteger counter = new AtomicInteger(0);
+
+ private static final Comparator USER_COMPARATOR = Comparator.comparing(User::getName);
+
+ @Override
+ public User save(User user) {
+ Objects.requireNonNull(user);
+ if (user.isNew()) {
+ user.setId(counter.incrementAndGet());
+ }
+ repository.put(user.getId(), user);
+ return user;
+ }
+
+ @PostConstruct
+ public void postConstruct() {
+ LOG.info("+++ PostConstruct");
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ LOG.info("+++ PreDestroy");
+ }
+
+ @Override
+ public boolean delete(int id) {
+ return repository.remove(id) != null;
+ }
+
+ @Override
+ public User get(int id) {
+ return repository.get(id);
+ }
+
+ @Override
+ public List getAll() {
+ return repository.values().stream()
+ .sorted(USER_COMPARATOR)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public User getByEmail(String email) {
+ Objects.requireNonNull(email);
+ return repository.values().stream()
+ .filter(u -> email.equals(u.getEmail()))
+ .findFirst()
+ .orElse(null);
+ }
+}
diff --git a/src/test/java/ru/javawebinar/topjava/service/MealServiceTest.java b/src/test/java/ru/javawebinar/topjava/service/MealServiceTest.java
new file mode 100644
index 000000000000..f944d9c9787a
--- /dev/null
+++ b/src/test/java/ru/javawebinar/topjava/service/MealServiceTest.java
@@ -0,0 +1,92 @@
+package ru.javawebinar.topjava.service;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import ru.javawebinar.topjava.MealTestData;
+import ru.javawebinar.topjava.model.Meal;
+import ru.javawebinar.topjava.util.DbPopulator;
+import ru.javawebinar.topjava.util.exception.NotFoundException;
+
+import java.time.LocalDate;
+import java.time.Month;
+import java.util.Arrays;
+
+import static ru.javawebinar.topjava.MealTestData.*;
+import static ru.javawebinar.topjava.UserTestData.ADMIN_ID;
+import static ru.javawebinar.topjava.UserTestData.USER_ID;
+
+@ContextConfiguration({
+ "classpath:spring/spring-app.xml",
+ "classpath:spring/spring-db.xml"
+})
+@RunWith(SpringJUnit4ClassRunner.class)
+public class MealServiceTest {
+
+ @Autowired
+ protected MealService service;
+
+ @Autowired
+ private DbPopulator dbPopulator;
+
+ @Before
+ public void setUp() throws Exception {
+ dbPopulator.execute();
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ service.delete(MealTestData.MEAL1_ID, USER_ID);
+ MATCHER.assertCollectionEquals(Arrays.asList(MEAL6, MEAL5, MEAL4, MEAL3, MEAL2), service.getAll(USER_ID));
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testDeleteNotFound() throws Exception {
+ service.delete(MEAL1_ID, 1);
+ }
+
+ @Test
+ public void testSave() throws Exception {
+ Meal created = getCreated();
+ service.save(created, USER_ID);
+ MATCHER.assertCollectionEquals(Arrays.asList(created, MEAL6, MEAL5, MEAL4, MEAL3, MEAL2, MEAL1), service.getAll(USER_ID));
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ Meal actual = service.get(ADMIN_MEAL_ID, ADMIN_ID);
+ MATCHER.assertEquals(ADMIN_MEAL1, actual);
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testGetNotFound() throws Exception {
+ service.get(MEAL1_ID, ADMIN_ID);
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ Meal updated = getUpdated();
+ service.update(updated, USER_ID);
+ MATCHER.assertEquals(updated, service.get(MEAL1_ID, USER_ID));
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testNotFoundUpdate() throws Exception {
+ Meal item = service.get(MEAL1_ID, USER_ID);
+ service.update(item, ADMIN_ID);
+ }
+
+ @Test
+ public void testGetAll() throws Exception {
+ MATCHER.assertCollectionEquals(MEALS, service.getAll(USER_ID));
+ }
+
+ @Test
+ public void testGetBetween() throws Exception {
+ MATCHER.assertCollectionEquals(Arrays.asList(MEAL3, MEAL2, MEAL1),
+ service.getBetweenDates(LocalDate.of(2015, Month.MAY, 30), LocalDate.of(2015, Month.MAY, 30), USER_ID));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/ru/javawebinar/topjava/service/UserServiceTest.java b/src/test/java/ru/javawebinar/topjava/service/UserServiceTest.java
new file mode 100644
index 000000000000..48d1f0a36a9d
--- /dev/null
+++ b/src/test/java/ru/javawebinar/topjava/service/UserServiceTest.java
@@ -0,0 +1,94 @@
+package ru.javawebinar.topjava.service;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import ru.javawebinar.topjava.model.Role;
+import ru.javawebinar.topjava.model.User;
+import ru.javawebinar.topjava.util.DbPopulator;
+import ru.javawebinar.topjava.util.exception.NotFoundException;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import static ru.javawebinar.topjava.UserTestData.*;
+
+@ContextConfiguration({
+ "classpath:spring/spring-app.xml",
+ "classpath:spring/spring-db.xml"
+})
+@RunWith(SpringJUnit4ClassRunner.class)
+public class UserServiceTest {
+
+ @Autowired
+ protected UserService service;
+
+ @Autowired
+ private DbPopulator dbPopulator;
+
+ @Before
+ public void setUp() throws Exception {
+ dbPopulator.execute();
+ }
+
+ @Test
+ public void testSave() throws Exception {
+ User newUser = new User(null, "New", "new@gmail.com", "newPass", 1555, false, Collections.singleton(Role.ROLE_USER));
+ User created = service.save(newUser);
+ newUser.setId(created.getId());
+ MATCHER.assertCollectionEquals(Arrays.asList(ADMIN, newUser, USER), service.getAll());
+ }
+
+ @Test(expected = DataAccessException.class)
+ public void testDuplicateMailSave() throws Exception {
+ service.save(new User(null, "Duplicate", "user@yandex.ru", "newPass", Role.ROLE_USER));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ service.delete(USER_ID);
+ MATCHER.assertCollectionEquals(Collections.singletonList(ADMIN), service.getAll());
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testNotFoundDelete() throws Exception {
+ service.delete(1);
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ User user = service.get(USER_ID);
+ MATCHER.assertEquals(USER, user);
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testGetNotFound() throws Exception {
+ service.get(1);
+ }
+
+ @Test
+ public void testGetByEmail() throws Exception {
+ User user = service.getByEmail("user@yandex.ru");
+ MATCHER.assertEquals(USER, user);
+ }
+
+ @Test
+ public void testGetAll() throws Exception {
+ Collection all = service.getAll();
+ MATCHER.assertCollectionEquals(Arrays.asList(ADMIN, USER), all);
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ User updated = new User(USER);
+ updated.setName("UpdatedName");
+ updated.setCaloriesPerDay(330);
+ service.update(updated);
+ MATCHER.assertEquals(updated, service.get(USER_ID));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/ru/javawebinar/topjava/web/InMemoryAdminRestControllerSpringTest.java b/src/test/java/ru/javawebinar/topjava/web/InMemoryAdminRestControllerSpringTest.java
new file mode 100644
index 000000000000..9396810afe48
--- /dev/null
+++ b/src/test/java/ru/javawebinar/topjava/web/InMemoryAdminRestControllerSpringTest.java
@@ -0,0 +1,54 @@
+package ru.javawebinar.topjava.web;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import ru.javawebinar.topjava.UserTestData;
+import ru.javawebinar.topjava.model.User;
+import ru.javawebinar.topjava.repository.UserRepository;
+import ru.javawebinar.topjava.util.exception.NotFoundException;
+import ru.javawebinar.topjava.web.user.AdminRestController;
+
+import java.util.Collection;
+
+import static ru.javawebinar.topjava.UserTestData.ADMIN;
+import static ru.javawebinar.topjava.UserTestData.USER;
+
+/**
+ * GKislin
+ * 13.03.2015.
+ */
+@ContextConfiguration("classpath:spring/spring-app.xml")
+@RunWith(SpringJUnit4ClassRunner.class)
+public class InMemoryAdminRestControllerSpringTest {
+
+ @Autowired
+ private AdminRestController controller;
+
+ @Autowired
+ private UserRepository repository;
+
+ @Before
+ public void setUp() throws Exception {
+ repository.getAll().forEach(u -> repository.delete(u.getId()));
+ repository.save(USER);
+ repository.save(ADMIN);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ controller.delete(UserTestData.USER_ID);
+ Collection users = controller.getAll();
+ Assert.assertEquals(users.size(), 1);
+ Assert.assertEquals(users.iterator().next(), ADMIN);
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testDeleteNotFound() throws Exception {
+ controller.delete(10);
+ }
+}
diff --git a/src/test/java/ru/javawebinar/topjava/web/InMemoryAdminRestControllerTest.java b/src/test/java/ru/javawebinar/topjava/web/InMemoryAdminRestControllerTest.java
new file mode 100644
index 000000000000..becff75a3425
--- /dev/null
+++ b/src/test/java/ru/javawebinar/topjava/web/InMemoryAdminRestControllerTest.java
@@ -0,0 +1,55 @@
+package ru.javawebinar.topjava.web;
+
+import org.junit.*;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import ru.javawebinar.topjava.UserTestData;
+import ru.javawebinar.topjava.model.User;
+import ru.javawebinar.topjava.repository.UserRepository;
+import ru.javawebinar.topjava.util.exception.NotFoundException;
+import ru.javawebinar.topjava.web.user.AdminRestController;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import static ru.javawebinar.topjava.UserTestData.ADMIN;
+import static ru.javawebinar.topjava.UserTestData.USER;
+
+public class InMemoryAdminRestControllerTest {
+ private static ConfigurableApplicationContext appCtx;
+ private static AdminRestController controller;
+
+ @BeforeClass
+ public static void beforeClass() {
+ appCtx = new ClassPathXmlApplicationContext("spring/spring-app.xml");
+ System.out.println("\n" + Arrays.toString(appCtx.getBeanDefinitionNames()) + "\n");
+ controller = appCtx.getBean(AdminRestController.class);
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ appCtx.close();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Re-initialize
+ UserRepository repository = appCtx.getBean(UserRepository.class);
+ repository.getAll().forEach(u -> repository.delete(u.getId()));
+ repository.save(USER);
+ repository.save(ADMIN);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ controller.delete(UserTestData.USER_ID);
+ Collection users = controller.getAll();
+ Assert.assertEquals(users.size(), 1);
+ Assert.assertEquals(users.iterator().next(), ADMIN);
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void testDeleteNotFound() throws Exception {
+ controller.delete(10);
+ }
+}
\ No newline at end of file