From 9a915901af244200f119a1f4b36bb4b743c4be06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Gonz=C3=A1lez?= Date: Sat, 18 Jun 2016 19:22:30 +0200 Subject: [PATCH] Add mock-comparisons module (#453) * Add new module for mocks comparison. * Add sources for testing. * Changes on testCase. * Enter some tests for mockito. * More tests for Mockito. * Even more tests. * Add the rest of the mocking libraries. * Javadoc on test. * Test bare bones for EasyMock. * Fist kind of test and setup. * Add tests using EasyMock with a change on LoginService. * Create LoginControllerTest.java * Test setup * [JMockit] No method called test. * [JMockit] Two methods called test. * [JMockit] One method called test. * [JMockit] Exception mock test * [JMockit] Mocked object to pass around test. * [JMockit] Custom matcher test. * [JMockit] Partial mocking test. * [JMockit] Fix with IDE. * Not stubs. Mocks. MOCKS!!! * Remove unnecesary import. --- mock-comparisons/README.md | 7 + mock-comparisons/pom.xml | 105 +++++++++++++ .../mocks/testCase/LoginController.java | 29 ++++ .../org/baeldung/mocks/testCase/LoginDao.java | 9 ++ .../baeldung/mocks/testCase/LoginService.java | 33 ++++ .../org/baeldung/mocks/testCase/UserForm.java | 15 ++ .../mocks/easymock/LoginControllerTest.java | 147 +++++++++++++++++ .../mocks/jmockit/LoginControllerTest.java | 148 ++++++++++++++++++ .../mocks/mockito/LoginControllerTest.java | 129 +++++++++++++++ pom.xml | 1 + 10 files changed, 623 insertions(+) create mode 100644 mock-comparisons/README.md create mode 100644 mock-comparisons/pom.xml create mode 100644 mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java create mode 100644 mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java create mode 100644 mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java create mode 100644 mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java create mode 100644 mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java create mode 100644 mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java create mode 100644 mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java diff --git a/mock-comparisons/README.md b/mock-comparisons/README.md new file mode 100644 index 0000000000..7795487b77 --- /dev/null +++ b/mock-comparisons/README.md @@ -0,0 +1,7 @@ +========= + +## Mock comparison realated tutorials + + +### Relevant Articles: +- [Mockito vs EasyMock vs JMockit](http://www.baeldung.com/mockito-vs-easymock-vs-jmockit) diff --git a/mock-comparisons/pom.xml b/mock-comparisons/pom.xml new file mode 100644 index 0000000000..c7a6dcb09d --- /dev/null +++ b/mock-comparisons/pom.xml @@ -0,0 +1,105 @@ + + 4.0.0 + org.baeldung + mock-comparisons + 0.1-SNAPSHOT + + mockito + + + + + + + + + + + junit + junit + ${junit.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.easymock + easymock + ${easymock.version} + test + + + + org.jmockit + jmockit + ${jmockit.version} + test + + + + + + mock-comparisons + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.7 + 1.7 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + + + + + + + + + + + + 4.12 + 1.10.19 + 3.4 + 1.24 + + + 3.3 + 2.6 + 2.18.1 + 2.7 + 1.4.14 + + + + \ No newline at end of file diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java new file mode 100644 index 0000000000..2e25332db8 --- /dev/null +++ b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java @@ -0,0 +1,29 @@ +package org.baeldung.mocks.testCase; + +public class LoginController { + + public LoginService loginService; + + public String login(UserForm userForm){ + if(null == userForm){ + return "ERROR"; + }else{ + boolean logged; + + try { + logged = loginService.login(userForm); + } catch (Exception e) { + return "ERROR"; + } + + if(logged){ + loginService.setCurrentUser(userForm.getUsername()); + return "OK"; + }else{ + return "KO"; + } + } + } + + // standard setters and getters +} diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java new file mode 100644 index 0000000000..4641fc1889 --- /dev/null +++ b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java @@ -0,0 +1,9 @@ +package org.baeldung.mocks.testCase; + +public class LoginDao { + + public int login(UserForm userForm){ + //actual call to a third party library + return 0; + } +} diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java new file mode 100644 index 0000000000..2a20159393 --- /dev/null +++ b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java @@ -0,0 +1,33 @@ +package org.baeldung.mocks.testCase; + +public class LoginService { + + private LoginDao loginDao; + + private String currentUser; + + public boolean login(UserForm userForm) { + assert null != userForm; + + int loginResults = loginDao.login(userForm); + + switch (loginResults){ + case 1: + return true; + default: + return false; + } + } + + public void setCurrentUser(String username) { + if(null != username){ + this.currentUser = username; + } + } + + public void setLoginDao(LoginDao loginDao) { + this.loginDao = loginDao; + } + + // standard setters and getters +} diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java new file mode 100644 index 0000000000..d6ee444909 --- /dev/null +++ b/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java @@ -0,0 +1,15 @@ +package org.baeldung.mocks.testCase; + +public class UserForm { + + // public access modifiers as only for testing + + public String password; + + public String username; + + public String getUsername(){ + return username; + } + +} diff --git a/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java b/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java new file mode 100644 index 0000000000..b80c28804a --- /dev/null +++ b/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java @@ -0,0 +1,147 @@ +package org.baeldung.mocks.easymock; + +import org.baeldung.mocks.testCase.LoginController; +import org.baeldung.mocks.testCase.LoginDao; +import org.baeldung.mocks.testCase.LoginService; +import org.baeldung.mocks.testCase.UserForm; +import org.easymock.*; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + *

Test for LoginController using EasyMock.

+ * Created by Alvaro on 12/06/2016. + */ +@RunWith(EasyMockRunner.class) +public class LoginControllerTest { + + @Mock + private LoginDao loginDao; + + @Mock + private LoginService loginService; + + @TestSubject + private LoginController loginController = new LoginController(); + + @Test + public void assertThatNoMethodHasBeenCalled() { + EasyMock.replay(loginService); + loginController.login(null); + + // no method called + EasyMock.verify(loginService); + } + + @Test + public void assertTwoMethodsHaveBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + EasyMock.expect(loginService.login(userForm)).andReturn(true); + loginService.setCurrentUser("foo"); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + EasyMock.verify(loginService); + } + + @Test + public void assertOnlyOneMethodHasBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + EasyMock.expect(loginService.login(userForm)).andReturn(false); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("KO", login); + EasyMock.verify(loginService); + } + + @Test + public void mockExceptionThrowing() { + UserForm userForm = new UserForm(); + EasyMock.expect(loginService.login(userForm)).andThrow(new IllegalArgumentException()); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("ERROR", login); + EasyMock.verify(loginService); + } + + @Test + public void mockAnObjectToPassAround() { + UserForm userForm = EasyMock.mock(UserForm.class); + EasyMock.expect(userForm.getUsername()).andReturn("foo"); + EasyMock.expect(loginService.login(userForm)).andReturn(true); + loginService.setCurrentUser("foo"); + EasyMock.replay(userForm); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + EasyMock.verify(userForm); + EasyMock.verify(loginService); + } + + @Test + public void argumentMatching() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // default matcher + EasyMock.expect(loginService.login(EasyMock.isA(UserForm.class))).andReturn(true); + // complex matcher + loginService.setCurrentUser(specificArgumentMatching("foo")); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + EasyMock.verify(loginService); + } + + private static String specificArgumentMatching(final String expected) { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object argument) { + return argument instanceof String && ((String) argument).startsWith(expected); + } + + @Override + public void appendTo(StringBuffer buffer) { + //NOOP + } + }); + return null; + } + + @Test + public void partialMocking() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // use partial mock + LoginService loginServicePartial = EasyMock.partialMockBuilder(LoginService.class). + addMockedMethod("setCurrentUser").createMock(); + loginServicePartial.setCurrentUser("foo"); + // let service's login use implementation so let's mock DAO call + EasyMock.expect(loginDao.login(userForm)).andReturn(1); + + loginServicePartial.setLoginDao(loginDao); + loginController.loginService = loginServicePartial; + + EasyMock.replay(loginDao); + EasyMock.replay(loginServicePartial); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + // verify mocked call + EasyMock.verify(loginServicePartial); + EasyMock.verify(loginDao); + } +} diff --git a/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java b/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java new file mode 100644 index 0000000000..d1c502ce55 --- /dev/null +++ b/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java @@ -0,0 +1,148 @@ +package org.baeldung.mocks.jmockit; + +import mockit.*; +import mockit.integration.junit4.JMockit; +import org.baeldung.mocks.testCase.LoginController; +import org.baeldung.mocks.testCase.LoginDao; +import org.baeldung.mocks.testCase.LoginService; +import org.baeldung.mocks.testCase.UserForm; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + *

Test for LoginController using JMockit.

+ * Created by Alvaro on 12/06/2016. + */ +@RunWith(JMockit.class) +public class LoginControllerTest { + + @Injectable + private LoginDao loginDao; + + @Injectable + private LoginService loginService; + + @Tested + private LoginController loginController; + + @Test + public void assertThatNoMethodHasBeenCalled() { + loginController.login(null); + // no method called + new FullVerifications(loginService) {}; + } + + @Test + public void assertTwoMethodsHaveBeenCalled() { + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + new Expectations() {{ + loginService.login(userForm); result = true; + loginService.setCurrentUser("foo"); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + new FullVerifications(loginService) {}; + } + + @Test + public void assertOnlyOneMethodHasBeenCalled() { + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + new Expectations() {{ + loginService.login(userForm); result = false; + // no expectation for setCurrentUser + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("KO", login); + new FullVerifications(loginService) {}; + } + + @Test + public void mockExceptionThrowing() { + final UserForm userForm = new UserForm(); + new Expectations() {{ + loginService.login(userForm); result = new IllegalArgumentException(); + // no expectation for setCurrentUser + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("ERROR", login); + new FullVerifications(loginService) {}; + } + + @Test + public void mockAnObjectToPassAround(@Mocked final UserForm userForm) { + new Expectations() {{ + userForm.getUsername(); result = "foo"; + loginService.login(userForm); result = true; + loginService.setCurrentUser("foo"); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + new FullVerifications(loginService) {}; + new FullVerifications(userForm) {}; + } + + @Test + public void argumentMatching() { + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + // default matcher + new Expectations() {{ + loginService.login((UserForm) any); + result = true; + // complex matcher + loginService.setCurrentUser(withArgThat(new BaseMatcher() { + @Override + public boolean matches(Object item) { + return item instanceof String && ((String) item).startsWith("foo"); + } + + @Override + public void describeTo(Description description) { + //NOOP + } + })); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + new FullVerifications(loginService) {}; + } + + @Test + public void partialMocking() { + // use partial mock + final LoginService partialLoginService = new LoginService(); + partialLoginService.setLoginDao(loginDao); + loginController.loginService = partialLoginService; + + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + // let service's login use implementation so let's mock DAO call + new Expectations() {{ + loginDao.login(userForm); result = 1; + // no expectation for loginService.login + partialLoginService.setCurrentUser("foo"); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + // verify mocked call + new FullVerifications(partialLoginService) {}; + new FullVerifications(loginDao) {}; + } +} diff --git a/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java b/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java new file mode 100644 index 0000000000..841dd493e6 --- /dev/null +++ b/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java @@ -0,0 +1,129 @@ +package org.baeldung.mocks.mockito; + +import org.baeldung.mocks.testCase.LoginController; +import org.baeldung.mocks.testCase.LoginDao; +import org.baeldung.mocks.testCase.LoginService; +import org.baeldung.mocks.testCase.UserForm; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; + +/** + *

Test for LoginController using Mockito.

+ * Created by Alvaro on 12/06/2016. + */ +public class LoginControllerTest { + + @Mock + private LoginDao loginDao; + + @Spy + @InjectMocks + private LoginService spiedLoginService; + + @Mock + private LoginService loginService; + + @InjectMocks + private LoginController loginController; + + @Before + public void setUp() { + loginController = new LoginController(); + MockitoAnnotations.initMocks(this); + } + + @Test + public void assertThatNoMethodHasBeenCalled() { + loginController.login(null); + // no method called + Mockito.verifyZeroInteractions(loginService); + } + + @Test + public void assertTwoMethodsHaveBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + Mockito.when(loginService.login(userForm)).thenReturn(true); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + Mockito.verify(loginService).login(userForm); + Mockito.verify(loginService).setCurrentUser("foo"); + } + + @Test + public void assertOnlyOneMethodHasBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + Mockito.when(loginService.login(userForm)).thenReturn(false); + + String login = loginController.login(userForm); + + Assert.assertEquals("KO", login); + Mockito.verify(loginService).login(userForm); + Mockito.verifyNoMoreInteractions(loginService); + } + + @Test + public void mockExceptionThrowing() { + UserForm userForm = new UserForm(); + Mockito.when(loginService.login(userForm)).thenThrow(IllegalArgumentException.class); + + String login = loginController.login(userForm); + + Assert.assertEquals("ERROR", login); + Mockito.verify(loginService).login(userForm); + Mockito.verifyZeroInteractions(loginService); + } + + @Test + public void mockAnObjectToPassAround() { + UserForm userForm = Mockito.when(Mockito.mock(UserForm.class).getUsername()).thenReturn("foo").getMock(); + Mockito.when(loginService.login(userForm)).thenReturn(true); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + Mockito.verify(loginService).login(userForm); + Mockito.verify(loginService).setCurrentUser("foo"); + } + + @Test + public void argumentMatching() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // default matcher + Mockito.when(loginService.login(Mockito.any(UserForm.class))).thenReturn(true); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + Mockito.verify(loginService).login(userForm); + // complex matcher + Mockito.verify(loginService).setCurrentUser(Mockito.argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object argument) { + return argument instanceof String && ((String) argument).startsWith("foo"); + } + })); + } + + @Test + public void partialMocking() { + // use partial mock + loginController.loginService = spiedLoginService; + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // let service's login use implementation so let's mock DAO call + Mockito.when(loginDao.login(userForm)).thenReturn(1); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + // verify mocked call + Mockito.verify(spiedLoginService).setCurrentUser("foo"); + } +} diff --git a/pom.xml b/pom.xml index 85861685ba..f16861cc68 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ jooq-spring json-path mockito + mock-comparisons jee7schedule querydsl