My Problems:
I can test successfully for CRUD services operation. I was doing an insert on @Before [setUp()] and delete of same data on @Aft
Speculation: do you really need to test the transaction? Or just the business logic around the db access? Because if so, you could try writing the unit test with EasyMock (or similar), avoiding the access to the database yet testing the functionality
I use for JUnit testing mockito framework and inject the services over PortalBeanLocatorUtil.setBeanLocator(...)
-methode. I think that is clearly as to do this with spring configuration. Here you have full example how it can be used. The example is shot and that is good so, because the approach is simple and understandable.
package mst.unittest.example;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Before;
import org.junit.Test;
import com.liferay.portal.kernel.bean.BeanLocator;
import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalService;
import com.liferay.portal.service.UserLocalServiceUtil;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* @author mark.stein.ms@gmail.com
*/
public class MyUserUtilTest {
private BeanLocator mockBeanLocator;
@Before
public void init() {
//create mock for BeanLocator, BeanLocator is responsible for loading of Services
mockBeanLocator = mock(BeanLocator.class);
//... and insert it in Liferay loading infrastructure (instead of Spring configuration)
PortalBeanLocatorUtil.setBeanLocator(mockBeanLocator);
}
@Test
public void testIsUserFullAge() throws PortalException, SystemException, ParseException {
//setup
SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd");
Date D2000_01_01 = format.parse("2000_01_01");
Date D1990_06_30 = format.parse("1990_06_30");
UserLocalService mockUserLocalService = mock(UserLocalService.class);
User mockUserThatIsFullAge = mock(User.class);
when(mockUserThatIsFullAge.getBirthday()).thenReturn(D1990_06_30);
User mockUserThatIsNotFullAge = mock(User.class);
when(mockUserThatIsNotFullAge.getBirthday()).thenReturn(D2000_01_01);
//overwrite getUser(...) methode so that wir get mock user-object with mocked behavior
when(mockUserLocalService.getUser(1234567)).thenReturn(mockUserThatIsFullAge);
when(mockUserLocalService.getUser(7654321)).thenReturn(mockUserThatIsNotFullAge);
//load our mock-object instead of default UserLocalService
when(mockBeanLocator.locate("com.liferay.portal.service.UserLocalService")).thenReturn(mockUserLocalService);
//run
User userFullAge = UserLocalServiceUtil.getUser(1234567);
boolean fullAge = MyUserUtil.isUserFullAge(userFullAge);
//verify
assertTrue(fullAge);
//run
User userNotFullAge = UserLocalServiceUtil.getUser(7654321);
boolean notfullAge = MyUserUtil.isUserFullAge(userNotFullAge);
//verify
assertFalse(notfullAge);
}
}
class MyUserUtil {
public static boolean isUserFullAge(User user) throws PortalException, SystemException {
Date birthday = user.getBirthday();
long years = (System.currentTimeMillis() - birthday.getTime()) / ((long)365*24*60*60*1000);
return years > 18;
}
}
You can use this approach also without mockito framework, then you must create the mock-classes like MockBeanLocator
manually.
Approach with PowerMock
With PowerMock you can to abdicate BeanLocator
because PowerMock allows to override static methods. Here the same example with PowerMock:
package mst.unittest.example;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* @author Mark Stein
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(UserLocalServiceUtil.class)
public class LiferayAndPowerMockTest {
@Test
public void testIsUserFullAge() throws PortalException, SystemException, ParseException {
//setup
SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd");
Date D2000_01_01 = format.parse("2000_01_01");
Date D1990_06_30 = format.parse("1990_06_30");
User mockUserThatIsFullAge = mock(User.class);
when(mockUserThatIsFullAge.getBirthday()).thenReturn(D1990_06_30);
User mockUserThatIsNotFullAge = mock(User.class);
when(mockUserThatIsNotFullAge.getBirthday()).thenReturn(D2000_01_01);
//overwrite getUser(...) by UserLocalServiceUtil methode so that wir get mock user-object with mocked behavior
PowerMockito.mockStatic(UserLocalServiceUtil.class);
when(UserLocalServiceUtil.getUser(1234567)).thenReturn(mockUserThatIsFullAge);
when(UserLocalServiceUtil.getUser(7654321)).thenReturn(mockUserThatIsNotFullAge);
//run
boolean fullAge = MySecUserUtil.isUserFullAge(1234567);
//verify
assertTrue(fullAge);
//run
boolean notfullAge = MySecUserUtil.isUserFullAge(7654321);
//verify
assertFalse(notfullAge);
}
}
class MySecUserUtil {
public static boolean isUserFullAge(long userId) throws PortalException, SystemException {
User user = UserLocalServiceUtil.getUser(userId);
Date birthday = user.getBirthday();
long years = (System.currentTimeMillis() - birthday.getTime()) / ((long)365*24*60*60*1000);
return years > 18;
}
}
Here you found PowerMock 1.4.12 with Mockito and JUnit including dependencies http://code.google.com/p/powermock/downloads/detail?name=powermock-mockito-junit-1.4.12.zip&can=2&q=