Hot questions for Using Mockito in jmock

Question:

I am using private static final LOGGER field in my class and I want LOGGER.isInfoEnabled() method to return false. How can I mock the static final field by using mockito or jMockit

My class is:

  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  public class Class1 {

  private static final Logger LOGGER = LoggerFactory.getLogger(Class1.class);

    public boolean demoMethod() {
       System.out.println("Demo started");
       if (LOGGER.isInfoEnabled()) {
         System.out.println("@@@@@@@@@@@@@@ ------- info is enabled");
       } else {
         System.out.println("info is disabled");
       }
       return LOGGER.isInfoEnabled();
    }
  }

and its junit is :

import mockit.Mocked;
import mockit.NonStrictExpectations;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import static org.testng.Assert.*;
import com.source.Class1;

public class MyTest {

  @InjectMocks
  Class1 cls1;

  @BeforeMethod
  public void initMocks() {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void test(@Mocked final Logger LOGGER) {

    new NonStrictExpectations() {
      {
        LOGGER.isInfoEnabled();
        result = false;
      }
    };
    assertFalse(cls1.demoMethod());
  }
}

when I run it the result is:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.test.MyTest
Configuring TestNG with: TestNG652Configurator
Demo started
@@@@@@@@@@@@@@ ------- info is enabled
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.9 sec <<< FAILURE! - in com.test.MyTest
test(com.test.MyTest)  Time elapsed: 0.168 sec  <<< FAILURE!
java.lang.AssertionError: expected [false] but found [true]
        at com.test.MyTest.test(MyTest.java:35)


Results :

Failed tests:
  MyTest.test:35 expected [false] but found [true]

Tests run: 1, Failures: 1, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.899s
[INFO] Finished at: Mon Jun 08 12:35:36 IST 2015
[INFO] Final Memory: 16M/166M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project JMockDemo: The
re are test failures.
[ERROR]
[ERROR] Please refer to D:\perfoce_code\workspace_kepler\JMockDemo\target\surefire-reports for the individual test results.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

I am new to jmockit and I want my above junit case to run successfully. And I have to use JMockit or mockito, can't use Powermockito. Please help.


Answer:

One way is using reflection get rid of final modifier from the field and then replace the LOGGER field with Mocked one

public class Class1Test {
    @Test
    public void test() throws Exception {
        Logger logger = Mockito.mock(Logger.class);
        Mockito.when(logger.isInfoEnabled()).thenReturn(false);
        setFinalStatic(Class1.class.getDeclaredField("LOGGER"), logger);
        Class1 cls1 = new Class1();
        assertFalse(cls1.demoMethod());
    }

    static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);        
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }
}

Question:

I have a Class A which has an internal Cache represented by a Class B. this inner class is private since the cache need not be visible to external consumers and is only to assist the outer class A. I am using Jmock and Java

public class A {
    ...
    private class B {
    ... 
       public void testMethod() {
          //The method I want to unit test
          ...
       }
    }
}

This is shown above. I am not sure how to unit test the testMethod() which is from private inner class B (as class B is not visible to the outer world).

Please advise!

Thanks!


Answer:

since the cache need not be visible to external consumers

A unit test is an external consumer. It's a class which invokes functionality on the object being tested, just like any other class.

Caveat: There is much opinion and debate on this matter. What I'm presenting here isn't "the one true answer" but is based on my own experience in maintaining unit tests in code.

Don't directly unit test private members. Not only does it generally take a little bit of trickery to make that happen, it creates coupling between the classes. (The test class and the class being tested.) Exposing the internals and coupling to them is a violation of object oriented principles.

Rather than thinking of your tests in terms of the methods you call on the class, think of your tests in terms of the functionality you invoke on the unit. Whatever functionality that unit exposes is what should be tested.

This leads to a few conclusions:

  • If there is no public functionality which internally invokes the private members in question, then why are those private members there at all? Just remove them.
  • If the private functionality is very complex and very difficult to invoke/validate using only public functionality then perhaps some refactoring is in order to simplify the class.

Since code which uses the object can only invoke the public functionality, code which tests the object should only validate the public functionality.

Question:

I am trying to replace JMock with Mockito (1.10.17). I have already done some unit tests successfully, but now I want to use the timeout feature

verify(publisher, timeout(5000)).notifySubscribers(any(BecameMasterMessage.class));

and I get this exception:

java.lang.VerifyError: (class: org/mockito/internal/verification/VerificationOverTimeImpl, method: verify signature: (Lorg/mockito/internal/verification/api/VerificationData;)V) Incompatible argument to function
    at org.mockito.verification.Timeout.<init>(Timeout.java:32)
    at org.mockito.verification.Timeout.<init>(Timeout.java:25)
    at org.mockito.Mockito.timeout(Mockito.java:2164)

The issue happens in IntelliJ and with Maven. There is only 1 version of Mockito on the classpath. There is also JMock 2.5.1 on the classpath which I cannot remove since 99% of my unit tests still use JMock at this moment. I don't know if that has anything to do with it.

UPDATE: I tried with JMock 2.6.0 and Hamcrest 1.3 but the result is the same.

UPDATE 2:

This works:

Thread.sleep( 5000 );
verify( m_publisher ).notifySubscribers( any( BecameMasterMessage.class ) );

And this does not:

verify(publisher, timeout(5000)).notifySubscribers(any(BecameMasterMessage.class));

UPDATE 3: I have made a small test project that has the exact same problem: See https://github.com/wimdeblauwe/mockito-verify-problem and run it from IntelliJ or with Maven.


Answer:

The problem here is an unfortunate constellation between TestNG, JUnit and Mockto. To fix your issue, you just need to add a dependency to JUnit 4.0 or greater (the most recent version is currently 4.12):

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
</dependency>

Here are the details:

TestNG, which is apparently your testing framework, declares a dependency to the quite old JUnit version 3.8.1. Mockito does not declare a dependency to JUnit at all but it uses some JUnit classes that were introduced in JUnit 4.0 (!).

Edit:

The method Mockito#timeout() in your example creates a Timeout instance which in turn creates an instance of VerificationOverTimeImpl. The method VerificationOverTimeImpl#verify() handles an error of type ArgumentsAreDifferent which is a subclass of org.junit.ComparisonFailure.

From JUnit version 3.8.1 to 4.x the class hierarchy of ComparisonFailure changed to having AssertionError instead of Error as base class. The VerifiyError is caused because VerificationOverTimeImpl#handleVerifyException() requires an AssertionError but would be invoked with an Error when JUnit 3.8.1 is used.

Question:

This 2013 post on SO asked how to use Hamcrest matchers to verify lists/collections invocations in Mockito. The accepted solution was to cast the Matcher to a (Collection).

I'm trying to do something similar, but running into a class cast error. I am not sure if I am misusing Hamcrest matchers, or if this usage simply isn't supported by Mockito. In my case, I'm trying to use a list of Matchers as my argument:

static class Collaborator
{
   void doSomething(Iterable<String> values) {}
}

@Test
public void usingMockito()
{
   Collaborator mock = Mockito.mock(Collaborator.class);
   mock.doSomething(Arrays.asList("a", "b"));

   // legal cast
   Mockito.verify(mock).doSomething((Collection<String>)argThat(Matchers.contains("a", "b")));
   // legal cast
   Mockito.verify(mock).doSomething((Collection<String>)argThat(Matchers.contains(Matchers.equalTo("a"), Matchers.equalTo("b"))));

   // illegal cast!!! Cannot cast from Iterable<capture#3-of ? extends List<Matcher<String>>> to Collection<String>
   Mockito.verify(mock).doSomething((Collection<String>)argThat(Matchers.contains(Arrays.asList(Matchers.equalTo("a"), Matchers.equalTo("b")))));
}

But I get the cast error:

Cannot cast from Iterable<capture#3-of ? extends List<Matcher<String>>> to Collection<String>

Am I doing something unsupported?


Answer:

As Jeff Bowman has already pointed out, the problem is that the compiler doesn't know which of the 4 contains methods you are trying to call.

The list you are constructing

Arrays.asList(Matchers.equalTo("a"), Matchers.equalTo("b"))

is of type

List<Matcher<String>>

but the contains method you want to call (<E> Matcher<Iterable<? extends E>> contains(List<Matcher<? super E>> itemMatchers)) expects a type

List<Matcher<? super String>>

as parameter. As your list type doesn't match the expected one, the compiler actually thinks that you are trying to call

<E> Matcher<Iterable<? extends E>> contains(E... items)

The solution: give the compiler what it wants. Create a List<Matcher<? super String>> instead of a List<Matcher<String>>:

        List<Matcher<? super String>> matchersList = new ArrayList<>();
        matchersList.add(Matchers.equalTo("a"));
        matchersList.add(Matchers.equalTo("b"));

        // no illegal cast anymore
        Mockito.verify(mock).doSomething(
            (Collection<String>) argThat(Matchers.contains(matchersList)));

EDIT:

Adding Jeff Bowman's inline solution from his comment, that enables the use of Arrays.asList as stated in the question:

        Mockito.verify(mock).doSomething(
                (Collection<String>) argThat(
                         Matchers.contains(
                                 Arrays.<Matcher<? super String>> asList(Matchers.equalTo("a"), Matchers.equalTo("b")))));

Question:

I found this article quite interesting http://www.jayway.com/2012/02/25/mockito-and-dependency-injection/ it says that Mockito supports dependency injection by using constructor arguments, setter methods and field injection. I was wondering if JMockit does the same, so far I haven't find no one using JMockit and dependency injection.


Answer:

JMockit supports dependency injection via arguments and properties. The test class must contain one or more mock properties or mock parameters declared to be @Injectable. The business object you would like to test need to be declared with the annotation @Tested. The @Tested annotation automatically creates an instance of the class and injecting the mocked dependencies.

public class SomeTest {
   @Tested CodeUnderTest tested;
   @Injectable Dependency dep1;
   @Injectable AnotherDependency dep2;
   @Injectable int someIntegralProperty = 123;

   @Test
   public void someTestMethod(@Injectable("true") boolean flag, @Injectable("Mary") String name)
   {
      // Record expectations on mocked types, if needed.

      tested.exerciseCodeUnderTest();

      // Verify expectations on mocked types, if required.
   }
}

You can find more detailed information here: http://jmockit.github.io/tutorial/BehaviorBasedTesting.html#tested (official docs)

Question:

I have seen a few examples of people switching from Mockito to JMockit, but I am doing the opposite. I am not really sure what to do with the @Mocked parameters. Do these just become @Mock instance variables? I think the NonStrictExpectations clause should become "when" clauses like:

when(rpManager.login()).thenReturn(true);

and the Verifications section becomes "verify" clauses.

This is an example of a full test case I am converting.

@Test
public void testGetOffersUnsuccessfulResponse(@Mocked final RPRequest mockRequest, @Mocked final RPResponse mockResponse) {

    final String sessionId = "123";

    new NonStrictExpectations() {{
        rpManager.login(); returns(true);
        rpManager.newRequest(anyString); returns(mockRequest);
        mockRequest.sendRequest(); returns(mockResponse);
        mockResponse.isSuccess(); returns(false);
    }};

    final EpiphanyConnection connection = new EpiphanyConnection(getDummyConnectionProperties(), getDummyActionMapping());
    assertTrue(connection.connect());

    final InteractionContext interactionContext = new InteractionContext();
    interactionContext.setRequestContext(new RequestContext());
    interactionContext.getRequestContext().setAction(getDummyActionMapping().keySet().iterator().next());

    interactionContext.setUserContext(new UserContext());
    interactionContext.getUserContext().setSessionId(sessionId);

    final OfferTranslator offerTranslator = connection.fetchCommunications(interactionContext);
    assertNotNull(offerTranslator);

    new Verifications() {{

        // failure in the below likely indicates mismatched JSON string.
        mockRequest.setData("SessionId", sessionId);
        mockRequest.sendRequest(); times=1;
    }};
}

Answer:

Mockito, you are correct there, does not expect any when clause to be actually needed. Like the name implies, WHEN this and that happens, then do something - if it did not happen, then that's ok as well.

To make sure that something has actually been called, use verify.

@Mock will create a mocked instance, correct:

@Mock
private MyService service; // will result in a mocked "MyService" instance

Don't forget to either call MockitoAnnotations.initMock(this); or to use @RunWith(MockitoJUnitRunner.class) to make sure the annotations are actually used.

Question:

I am using Scala 2.11. can I use Scala test or Mockito to mock Scala Classes? All the examples that I see on StackOverflow and other blogs are mocking scala Traits rather than classes. Also I tried to use JMockit and it does not seem to work with Scala.


Answer:

Using scalatest and the provided MockitoSugar module, you can do something like this (take from the official scalatest user guide)

// First, create the mock object
val mockCollaborator = mock[Collaborator]
// Create the class under test and pass the mock to it
classUnderTest = new ClassUnderTest
classUnderTest.addListener(mockCollaborator)

// Use the class under test
classUnderTest.addDocument("Document", new Array[Byte](0))
classUnderTest.addDocument("Document", new Array[Byte](0))
classUnderTest.addDocument("Document", new Array[Byte](0))
classUnderTest.addDocument("Document", new Array[Byte](0))

// Then verify the class under test used the mock object as expected
verify(mockCollaborator).documentAdded("Document")
verify(mockCollaborator, times(3)).documentChanged("Document")

Question:

In Mockito if you want a void method to do nothing you can do this:

doNothing().when(_mockedClass).voidMethod();

Is there a way to do this with JMockit?

I can't seem to find anything about it. I've been trying to switch to JMockit but am having trouble finding documentation for some of the things we do with Mockito. I suspect they are all there in one form or another, just having trouble finding them, so figured I'd start asking one question at a time here and hope there are easy answers! Thanks!


Answer:

Just like with Mockito, actually, if you want a method to do nothing, then simply don't record an expectation for it. Alternatively, you can record an expectation with no result, but there is really no need for that (or a point to it).

(This would only not be the case when using strict expectations (with new StrictExpectations() {{ ... }}), in which case all method invocations need to be accounted for.)

Question:

I have to mock a method using jmockit wich returns the same arguments I passed. With Mockito, I used AdditionalAnswers.returnsFirstArg:

PowerMockito.when(entityManager.merge((Request)Mockito.any())).then(AdditionalAnswers.returnsFirstArg());

How can i write this with jmockit?

new Expectations() {
        {
            entityManager.merge((Request) any);
            returns(????);
        }
    };

Thanks


Answer:

JMockit doesn't have this feature out-of-the-box, but it can be implemented easily enough, with a reusable Delegate class:

class FirstArgument implements Delegate<Object> {
    Object delegate(Invocation inv) { return inv.getInvokedArguments()[0]; }
}

@Mocked EntityManager entityManager;

@Test
public void expectationRecordedToReturnAnArgument()
{
    new Expectations() {{
        entityManager.merge(any);
        result = new FirstArgument();
    }};

    // From the code under test:
    EntityClass entity = new EntityClass();
    EntityClass merged = entityManager.merge(entity);

    assertSame(entity, merged);
}

Question:

I tried solution given in Exception : mockito wanted but not invoked, Actually there were zero interactions with this mock and this one too Mockito - Wanted but not invoked: Actually, there were zero interactions with this mock but Still getting the same error. Am I missing something? Here is me implementation:-

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Mockito.verify;

class ClassOne {
    public void method(ClassTwo two) {
    }
}

class ClassTwo {
    public ClassTwo(String value) {
    }
}

class MyClassTwo extends ClassTwo {
    public MyClassTwo(String value) {
        super(value);
    }
}

class ClassToBeTested {
    ClassOne classOne;

    public ClassToBeTested() {
        classOne = new ClassOne();
    }

    public void methodToBeTested() {
        ClassTwo event = new MyClassTwo("String");
        classOne.method(event);
    }
}

@RunWith(MockitoJUnitRunner.class)
public class ClassToBeTestedTest {

    ClassToBeTested presenter;
    @Mock
    ClassOne classOne;

    @Before
    public void setUp() {
        presenter = new ClassToBeTested();
    }


    @Test
    public void testAbc() {
        presenter.methodToBeTested();
        ClassTwo event = new MyClassTwo("someString");
        verify(classOne).method(event);
    }
}

Answer:

You need to pass in the mocked class (or do something horrid with PowerMock).

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Mockito.verify;

class ClassWeWantToBeMocked {
    void methodToBeMocked() { }
}

class ClassToBeTested {
    ClassWeWantToBeMocked dependency;

    // Notice that the dependency is now passed in. 
    // This is commonly called Dependency Injection.
    public ClassToBeTested(ClassWeWantToBeMocked dependency){
        this.dependency = dependency;
    }

    public void methodToBeTested(){
        dependency.methodToBeMocked();
    }
}

@RunWith(MockitoJUnitRunner.class)
public class ClassToBeTestedTest {

    ClassToBeTested presenter;

    @Mock
    ClassWeWantToBeMocked ourMock;

    @Before
    public void setUp(){
        // Notice how we now pass in the dependency (or in this case a mock)
        presenter=new ClassToBeTested(ourMock);
    }

    @Test
    public void myMockTest(){
        presenter.methodToBeTested();

        verify(ourMock).methodToBeMocked();
    }
}

Question:

Hello guys i want to test this code using moc╬║ito or JUNIT.

//Login Servlet

 @WebServlet("/login_controller")
public class login_controller extends HttpServlet {
private static final long serialVersionUID = 1L;

    private String  TAG="Login controller : ";
    private DataSource dataSource;
    private Connection connection;


    public void init() throws ServletException {
        connection=null;
        try {
            // Get DataSource
            Context initContext  = new InitialContext();
            Context envContext  = (Context)initContext.lookup("java:/comp/env");
            dataSource = (DataSource)envContext.lookup("jdbc/db");


        } catch (NamingException e) {
            e.printStackTrace();
        }
    }

/**
 * @see HttpServlet#HttpServlet()
 */
public login_controller() {
    super();
    // TODO Auto-generated constructor stub
}

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 */
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    doPost(request,response);
//  response.getWriter().append("Served at: ").append(request.getContextPath());
}

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
//  doGet(request, response);
     response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String userName=null;
    String password=null;
    boolean user_found= false;

    //Get parameters From HTTP request
    userName = request.getParameter("username");
    password = request.getParameter("password");


    if(userName == null || password ==null ||userName.equals("")||password.equals("")){
        System.out.println(TAG + "Username or Password =  Empty strings");
        RequestDispatcher rs = request.getRequestDispatcher("index.jsp");
           rs.forward(request, response);
           return;

    }
    System.out.println(TAG+"Username :" + userName+ "\t Password :"+password);
    System.out.println(TAG+"Remote IP address is " + request.getRemoteAddr());

    //Log USER loggin attempt
    LOG_IP_USER log =new LOG_IP_USER();
    USERS_DB user   =new USERS_DB();


    try {
        connection = dataSource.getConnection();
        user_found=user.authenticate(connection, userName, password);

    }
    catch (NoSuchAlgorithmException | SQLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    finally
      {
          try { if(null!=connection)connection.close();} catch (SQLException e) 
          {e.printStackTrace();}
      }


      if(user_found)//User found in the database
        {
          log.log(request.getRemoteAddr(),userName,true);  
          System.out.println(TAG + "Username"+userName);

           Cookie userNameCookie=new Cookie("username",userName);
            userNameCookie.setMaxAge(60*15);//15 minutes
            response.addCookie(userNameCookie);
            response.sendRedirect("userChoice.jsp"); 
            return;
        }
        else
        {   
            log.log(request.getRemoteAddr(),userName,false);
            out.println ("<script>alert('Invalid Username Or Password!');</script>");
           RequestDispatcher rs = request.getRequestDispatcher("index.jsp");
           rs.include(request, response);
        }




}

}

The method user.authenticate returns true if the user is found in the database. log.log (logs the ip address of the user and success or fail ) Can anyone help me with testing.


Answer:

Unit Testing can't be done on codes which involves database interactions.Those are covered in integration tests.However,if you want to test this under JUnit testing then You can mock the connection and return the values to test the scenarios using JMockit/Mockito.

//sample code using JMockit
@Test
public void testMyMethod(@Mocked final USERS_DB user){

new Expectations(){
             {
              user.authenticate(connection, userName, password);
              result = true/false/Exception();
            }};
//call method now to test

}

Also dont forget to mock the Context in the same way as well.