Hello guys, if you are writing unit test your Java application then you would
  have definitely come across JUnit and Mockito, two of the essential unit
  testing framework  for Java developers. While
  JUnit
  offers support to run your test, setup and teardown and also assertion to
  check the expected and actual output.
  Mockito
  complements JUnit by offering you a mock based testing approach. Mock is
  nothing but a test double which can return a configured value when a certain
  method is called. It also provides ability to check if a particular method is
  called or not. By using
  Mock object
  or test double you can check if your code is behaving properly or not in
  different scenarios. This is also the key difference between JUnit and
  Mockito, JUnit provides infrastructure to run your test while Mockito provide
  infrastructure to created Mock objects. 
  If you are wondering why do we need Mock object? can't we test with actual
  object then let me tell you that its not always possible to test with actual
  object without involving external dependencies like Database, or an external
  System. At that time, using Mock allows you to write unit test and unblock
  your development. 
  For example, recently I was developing a
  REST API client
  which calls an external service to retrieve discount coupon for products. If I
  have to write test for this client then I need the URL of external service to
  connect to their test environment which may or may not be ready. In order to
  overcome that problem, I can simply mock the HttpClient class which is used to
  connect to the third party service. 
  I can configure my Java 11 HttpClient
  to a dummy URL and then I can return the different kind of response to trigger
  different workflow in my application. For example, by using mock instance of
  HttpClient, I can return a
  successful response with code 200, an error response using 400 or even
  internal server error with 500 response code.  
  This gives me ability to test how my application behave in different
  scenarios. That's the power of Mockito, even with the actual object its not
  easy to mimic all these scenario and requires a lot of setup and effort for
  complete testing. That's why Java developer love Mockito, it help them to
  write better tests. 
  Btw, if you are serious about Unit testing and just looking for best online
  courses to learn unit testing in Java then you can also checkout this list of
  best JUnit and Mockito courses
  and if you like books, you can also read these
  best JUnit and Mockito books to learn both JUnit and Mockito in depth. 
How to use Mockito in Java? Example Tuotrial
  Now that you know what is Mockito and what does Mockito offer as well as when
  to use Mockito its good time to write code and see how easy or difficult it is
  to write Java unit tests using Mockito framework and library.  
  In this example, we have a
  GreetingService which return
  greeting message in different language at different time when you call it. For
  example, when you first call, it can return Namaste which is Hello in Hindi,
  similarly it can return greetings in Japanese also and we will use
  Mockito
  to configure this behavior. 
HelloWorld.java /** * Mockito is a leading mock framework for testing Java classes and interfaces. * In this Java program, we will see how we can use Mockito to test our Java * class, Helloworld, which greet with different message at different time. */ public class HelloWorld { private final GreetingService greetingService; public HelloWorld(GreetingService service) { this.greetingService = service; } public String greet() { return greetingService.getMessage(); } } interface GreetingService { public String getMessage(); }
HelloWorldTestWithMockito.java import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.junit.Test; import org.mockito.Mockito; public class HelloWorldTestWithMockito { private final HelloWorld helloWorldTest; private final GreetingService mockGreetingService; private final String greetInHindi = "Namaste !!"; private final String greetInEnglish = "Hello !!"; private final String greetInJapanese = "Moshi Moshi !!"; /* * Creating and Setting up mock objects */ public HelloWorldTestWithMockito() { this.mockGreetingService = mock(GreetingService.class); Mockito.when(mockGreetingService.getMessage()) .thenReturn(greetInHindi) .thenReturn(greetInEnglish) .thenReturn(greetInJapanese); this.helloWorldTest = new HelloWorld(mockGreetingService); } /* * Real testing starts now */ @Test public void greet() { final String firstMessage = helloWorldTest.greet(); final String secondMessage = helloWorldTest.greet(); final String thirdMessage = helloWorldTest.greet(); assertEquals(greetInHindi, firstMessage); assertEquals(greetInEnglish, secondMessage); assertEquals(greetInJapanese, thirdMessage); verify(mockGreetingService, times(2)).getMessage(); } }
  If you look closely, we have used a couple of Mockito methods in this program.
  First we have used
  Mockito.mock() to create a mock
  object of GreetingService class. In
  most program you will see just
  mock() because your
  IDE
  will use
  static import
  to import all static method from Mockito library. This will also make you to
  write less code and your code will also be more readable. 
  Once we got the Mock object you can configure it using
  when() and
    then() method. the when() method takes an argument which is an event like when
  getMessage() of GreetingService is called then you can return pre-configured
  object like greetInHindi in our case. In short, by using when() and then()
  method in Mockito you can sophistically configure your Mock object to mimic
  different scenarios under testing. 
  After that we have also used
  verify() method which is
  used for verification. By using verify() method you can double check which
  method of your class is called and how many times. For example, in our case we
  verified that getMessage() of GreetingService is called twice. If its not
  called twice then this test will fail and you will come to know about it,
  quite convenient? No?
Important points about Mockito Testing
  In order to create Mock object, there are a couple of requirement which your
  cla    ss need to follow. For example, your
  testing class must be public, which is not a requirement with JUnit but
  Mockito will not allow you to run if your test class is not public as shown in
  below error. 
java.lang.Exception: Class HellworldTestWithMockito should be public at org.junit.runners.model.FrameworkMethod.validatePublicVoid(FrameworkMethod.java:91) at org.junit.runners.model.FrameworkMethod.validatePublicVoidNoArg(FrameworkMethod.java:70) at org.junit.runners.ParentRunner.validatePublicVoidNoArgMethods(ParentRunner.java:133) at org.junit.runners.BlockJUnit4ClassRunner .validateTestMethods(BlockJUnit4ClassRunner.java:186) at org.junit.runners.BlockJUnit4ClassRunner .validateInstanceMethods(BlockJUnit4ClassRunner.java:166) at org.junit.runners.BlockJUnit4ClassRunner .collectInitializationErrors(BlockJUnit4ClassRunner.java:104) at org.junit.runners.ParentRunner.validate(ParentRunner.java:355)
Now this is to verify that whether Mockito actually record number of invocation to the method. I have put timed(2) to tell Mockito that this method should be called twice, since in code we are calling it three times. Mockito reports it as error :
org.mockito.exceptions.verification.TooManyActualInvocations: greetingService.getMessage(); Wanted 2 times: -> at HelloWorldTestWithMockito.greet(HelloWorldTestWithMockito.java:48) But was 3 times. Undesired invocation: -> at HelloWorld.greet(HelloWorld.java:23) at HelloWorldTestWithMockito.greet(HelloWorldTestWithMockito.java:48) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
Let's do one more test, in second call let's compare with first message. This should be reported by JUnit
org.junit.ComparisonFailure: expected:<[Hello] !!> but was:<[Namaste] !!> at org.junit.Assert.assertEquals(Assert.java:115) at org.junit.Assert.assertEquals(Assert.java:144) at HelloWorldTestWithMockito.greet(HelloWorldTestWithMockito.java:45)
    Similarly, your class also need a no-argument and default constructor and
    should not be final if you want to mock that class for testing. So make sure that if you want to mock your class then 
- It must be public
- It must not be final
- and It must have a no-argument constructor
And, here is a simple diagram which explains the difference between an actual object and mock object in Java:
  That's all about how to use Mockito in Java with JUnit. There is no
  doubt that Mockito is a great library and will help you to write better unit
  test. In many cases, it wasn't even possible to write JUnit test case without
  Mockito, hence a good knowledge of Mockito goes a long way for Java
  programmers. It will not only help you to write better and more sophisticated
  unit tests but also to become a better Java developer who is pro at unit
  testing.
 
 
 
 
 
 
 
 
 
 
 
 Posts
Posts
 
 
No comments :
Post a Comment