/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.commons.infrastructure.persistence;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;

import java.io.Serializable;

import javax.persistence.EntityManager;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import com.scytl.products.ov.commons.beans.exceptions.DuplicateEntryException;
import com.scytl.products.ov.commons.domain.model.BaseRepository;

/**
 * Test case for the class {@link com.scytl.products.ov.commons.infrastructure.persistence.BaseRepositoryImpl}. It is declared as abstract because the junit classes which extend it
 * will also launch its defined junits, otherwise these unit tests are not launched.
 */
@RunWith(MockitoJUnitRunner.class)
public abstract class BaseRepositoryImplTest<T, ID extends Serializable> {

	@Mock
	protected EntityManager entityManagerMock;

	protected Class<T> persistentClassMock;

	@InjectMocks
	protected BaseRepository<T, Serializable> baseRepository;

	private ID idMock;

	private T objectMock;

	private ID id;

	private T object;

	@Rule
	public ExpectedException expectedException = ExpectedException.none();

	@SuppressWarnings({"rawtypes", "unchecked" })
	public BaseRepositoryImplTest(final Class<T> entityClass, final Class<?> repositoryClass)
			throws InstantiationException, IllegalAccessException {
		this.persistentClassMock = entityClass;
		objectMock = entityClass.newInstance();
		baseRepository = (BaseRepository) repositoryClass.newInstance();
	}

	@Test
	public void findNull() {
		id = null;
		when(entityManagerMock.find(persistentClassMock, idMock)).thenReturn(null);

		assertNull(baseRepository.find(id));
	}

	@SuppressWarnings("unchecked")
	@Test
	public void find() {
		idMock = (ID) new Integer(1);
		id = idMock;
		when(entityManagerMock.find(persistentClassMock, idMock)).thenReturn(objectMock);

		T result = baseRepository.find(id);
		assertNotNull(result);
		assertEquals(objectMock, result);
	}

	@Test
	public void saveNull() throws DuplicateEntryException {
		object = null;
		doNothing().when(entityManagerMock).persist(objectMock);

		assertNull(baseRepository.save(object));
	}

	@Test
	public void save() throws DuplicateEntryException {
		doNothing().when(entityManagerMock).persist(objectMock);
		object = objectMock;

		assertNotNull(baseRepository.save(object));
	}
}
