Unit Tests are meant for testing single Methods of a Class only, without any other resources. Integration Tests, on the other hand, are meant for tests which include interaction between different resources (DataBase, Dependencies, etc.). Most Classes used in a Java EE Environment use other Classes with Dependency Injection.
Mockito is perfect for mocking / simulating that other resources, like Database access, etc. One "problem" with unit tests, in general, is that how to access fields marked with a private modifier and no setter. If you don't want to change the original class by using protected instead of private modifiers or add setter Methods, you can do your own DI by using the Java Reflection API.
Say you have a Backing Bean called ArticleModel which has a Dependency on another EJB Stateless Session Bean called ArticleService. The Backing Bean has a Method get ArticlePreview which returns a List of Strings with just the 1st 200 characters of all article text formatted with some HTML. The Article Model uses the injected EJB ArticleService to retrieve all Article Entities from the Database, iterates through them, abbreviates the Article Text of each Article and adds some HTML Tags.
To implement a Unit Test we now need a Mock for ArticleService, because we don’t have a DatabaseConnection. Also, we have to inject the Mock somehow into the ArticleModel Class because we don’t have DI in Unit Tests.
First lets take a look at the ArticleModel Class:
public class ArticleModel { //The Stateless Session bean which interacts with the DB @Inject private ArticleService articleService; public List<String> getAllArticlePreviews() { List<String> previews = new ArrayList<String>(); for(ArticleEntity article : articleService.findAllArticles()) { String t = article.getText(); t = t.substring(193); t = "<i>" + t + "</i>"; previews.add(t); } return previews; } }Now the ArticleService Class:
@Stateless public class ArticleService { @PersistenceContext(name = "persistenceUnitName") EntityManager em; public List<ArticleEntity> findAllArticles() { try { return em.createQuery("select a from Article a", ArticleEntity.class).getResultList(); } catch (Exception e) { // log return null; } } }Let's now create a Unit Test for the ArticleModel, a simple Test Class which keeps an instance of the ArticleModel, calls it's Methods and make some checks.
The ArticleModelTest Class could look like this:
public class ArticleModelTest { //The class to be tested private ArticleModel articleModel; @Before public void setUp() { articleModel = new ArticleModel(); } //the actual unit test @Test public void testGetAllArticlePreviews() throws Exception { ListThe above code will not work as it is, because articleModel depends on the ArticleService class which will be injected by CDI when deployed in JavaEE. When running the test it is null. Therefore we have to do 2 things. First is to setup a Mock for ArticleService which returns "dummy" Data. Then this mock needs to be injected into the ArticleModel.previews = articleModel.getAllArticlePreviews(); for(String preview : previews) { //simply test if preview text is not bigger than 200 chars Assert.assertTrue(preview.length() <= 200); ... } } }
The ArticleModelTest Class extended with Mockito and custom DI:
import org.mockito.Mock; import static org.mockito.Mockito.when; import org.mockito.MockitoAnnotations; public class ArticleModelTest { //The Mock for ArticleService @Mock ArticleService articleService; //The class to be tested private ArticleModel articleModel; @Before public void setUp() throws Exception { //needed for Mockito MockitoAnnotations.initMocks(this) //custom DI - inject the articleService into ArticleModel Class clazz = Class.forName("foo.bar.ArticleModel"); articleModel = (ArticleModel) clazz.newInstance(); Field[] fields = clazz.getDeclaredFields(); for (Field f : fields) { /** * the field articleService is private, * to inject it we have to set it accessible */ f.setAccessible(true); if (f.getName().equals("articleService")) { //inject the articleService into articleModel f.set(articleModel, articleService); } } } //the actual unit test @Test public void testGetAllArticlePreviews() throws Exception { /** * create a list with "dummy" ArticleEntities * which should be returned when ArticleModel * calls the ArticleService.findAllArticles() Method */ List<ArticleEntity> articles = new ArrayList<ArticleEntity>(); articles.add(new ArticleEntity("xxx")); ... articles.add(new ArticleEntity("yyy")); /** * this is to tell Mockito that our created list * should be returned whenever findAllArticles() is called */ when(articleService.findAllArticles()).thenReturn(articleList); List<String> previews = articleModel.getAllArticlePreviews(); for(String preview : previews) { //simply test if preview text is not bigger than 200 chars Assert.assertTrue(preview.length() <= 200); ... } } }now the Unit Test will work!