In our last post we discussed about how to unit test the DB layer in Seam. Let us see how easy it is to test the service layer now. When you are unit testing the service layer, then ideally you would only want to test the service layer. What that means is that we should not be doing an integration test which talks to the real dao’s. Instead, we should have the ability to mock any objects which the service layer interacts with so that we are just testing the business logic and nothing else.
This is where the combination of Mockito and SeamTest work very well. Let us see how.
Mockito would allow you to easily mock the other units that you do not want to test but your unit under test depends on them. SeamTest on the other hand allows you to inject the mocked objects into the unit under test using the setField method. Hence a simple test would look like this
@RunWith(MockitoJUnitRunner.class) public class IkeManagerActionTest extends SeamTest { @Mock private IkeSessionDao ikeSessionDao; @Mock private IkeDao ikeDao; @Mock private FacesMessages facesMessages; @Mock private Ike ike; @Test public void createIke() { IkeManagerAction ikeManagerAction = new IkeManagerAction(); setField(ikeManagerAction, "ikeDao", ikeDao); setField(ikeManagerAction, "facesMessages", facesMessages); ikeManagerAction.createIke(ike); verify(ikeDao, times(1)).createIke(ike); } @Test public void createIkeSession_WithMocks() { IkeManagerAction ikeManagerAction = new IkeManagerAction(); IkeSession ikeSession = mock(IkeSession.class); setField(ikeManagerAction, "ikeSessionDao", ikeSessionDao); setField(ikeManagerAction, "facesMessages", facesMessages); ikeManagerAction.createIkeSession(ikeSession, ike); verify(ikeSessionDao, times(1)).createIkeSession(ikeSession, ike); }
There are other mocking frameworks like easymock, rmock etc that you might want to use but the syntax and english like verbose statements of mockito make it a frontrunner in the mocking frameworks. Look at the following code snippet
@RunWith(MockitoJUnitRunner.class) public class ServiceInjectorTest extends SeamTest { private ServiceInjector serviceInjector; @Mock private User loggedInUser; @Mock private WebAppContextService webAppContextService; @Before public void setUp() { serviceInjector = new ServiceInjector(); setField(serviceInjector, "webAppContextService", webAppContextService); setField(serviceInjector, "loggedInUser", loggedInUser); } @Test public void testCompanyServiceReturnedForUserC1() { CompanyServiceC1 companyServiceC1 = new CompanyServiceC1(); when(loggedInUser.getUserType()).thenReturn(UserType.C1); when(webAppContextService.lookupBeanOrComponent("companyService"+UserType.C1)).thenReturn(companyServiceC1); Assert.assertEquals(serviceInjector.injectService("companyService"), companyServiceC1); } @Test public void testCompanyServiceReturnedForUserC2() { CompanyService companyService = new DemoCompanyService(); when(loggedInUser.getUserType()).thenReturn(UserType.C2); when(webAppContextService.lookupBeanOrComponent("companyService"+UserType.C2)).thenReturn(null); when(webAppContextService.lookupBeanOrComponent("companyService")).thenReturn(companyService); Assert.assertEquals(serviceInjector.injectService("companyService"), companyService); } }
Hence, as you would observe that unit testing the Service Layer is very easy in Seam.
Interested to know more about our JBoss Seam capabilities? Get in touch with us on seam@inphina.com
venkat akkineni
Thursday, April 21, 2011
Hello Vikas
I get no tests executed message in ide. I am able to compile the entire application without problem. But the test doesn’t execute.
I had to copy the components.xml and components.properties into the test path as it was complaining about jndiName.
I am using JUnit 4.4 so I had to use @RunWith(MockitoJUnit44Runner.class)
Would you help me with this.
Thanks
Venkat
@RunWith(MockitoJUnit44Runner.class)
public class VersionManagerActionTest extends SeamTest{
@Mock private Person person;
@Mock private Utilities utilities;
@Mock private Factories factories;
/**
* Test of add method, of class VersionManagerAction.
*/
@Test
public void addTest() {
VersionManagerAction instance = new VersionManagerAction();
Assert.assertNull(instance.getCurrent().getProduct());
instance.add();
Assert.assertNotNull(instance.getCurrent().getProduct());
}
}
venkat akkineni
Thursday, April 21, 2011
Oops
The method name should be testAdd() as opposed to addTest(). I changed it to see if the name is causing a problem. The tests don’t execute either way.