Hot questions for Using Mockito in bdd

Question:

Description

I am trying to test the following class:

Class UserSynchronizer(){
   private static org.apache.log4j.Logger log = ... ;

   public Sync(candidate) { 
     ...
     if (candidate.inValidForSync()) {
       log.debug("Candidate #" + candidate.getId() + ": Not syncing");
     }
     else {
       log.debug("Syncing");
     }
   }

 }

I want to see if mockito can detect what arguments log.debug was called with and then I want to see if I can do some kind of regex check on it. In other words, I want to:

  • capture the arguments provided to the log object (which I am mocking in my test atm)
  • check (using regex) if it matches a pattern like "Candidate #\d+: Not syncing" for the cases where my mock candidate object is returning false
Test code

The code below is what I have as a starting point:

public void verifySyncDoesntSyncWhenInvalid(){
  //Setup candidate mock
  Candidate invalidSyncCandidateMock = mock(Candidate.class);
  when(invalidSyncCandidateMock.inValidForSync()).thenReturn(true);

  //Setup log mock
  UserSynchronizer userSynchronizer = ...;
  Field logField = userSynchronizer.getClass().getDeclaredField("log");
  logField.setAccessible(true);
  logField.set(userSynchronizer, logMock);

  //Call sync
  userSynchronizer.sync(invalidSyncCandidateMock);

  //Verify that debug was called with ("Candidate #\d+: Not syncing")
  ???
}
Problem

The problem is that log.debug is called multiple times. I want to capture the arguments that are provided to log.debug and ensure that when it is called with the candidate that is invalid for sync, then the logger object correctly logs that the candidate was not synced.

Edit: If this has been asked before, I apologize. I kindly ask that you post a link to the related question :)


Answer:

Mockito provides regex matcher in standard org.mockito.Matchers class. Here is an example how this function can be used to verify invocation with proper parameter value:

verify(restMock, times(1)).exchange(matches(".*text=welcome.*to.*blah"), eq(HttpMethod.GET), any(ResponseEntity.class), eq(String.class));

Question:

The flow starts from the Controller.callMethod(). It calls a method which throws MyException. MyException is handled by an Exception handler written in the Controller:

public class Controller{

public Response callMethod() throws MyException {

   ClassToTest classToTest = new ClassToTest();
   return(classToTest.method());
   }


@ExceptionHandler(MyException.class)
public @ResponseBody
Response myException(HttpServletRequest req,
        HttpServletResponse res, MyException myException) {

    Response response = new Response();
    response.setResponseCode(myException.getErrorCode());       
    return response;
}

}


 public class ClassToTest {
    public Response method() throws MyException {
        Response response = anotherMethod();
        return response;
    }


    public String anotherMethod(){
        if(//something)
          throw new MyException(Constant.ERROR_CODE);    // I need to test this line
    else
        return //some response
    }
}


}

This is my Test class:

public class Test {

@Test
public void testMethod(){
try{
    ClassToTest classtotest = new ClassToTest();
    Response response  = classtotest.method();  //I want to get response after getting MyException (Response created by the myException ExceptionHandler)
    assertEquals("SUCCESS", response.getResponseCode);
  } catch(Exception e){
     //After getting MyException the control comes here & thats the problem. assertEquals never get executed.
  } }
}

When the line Response response = classtotest.method(); is executing then the control is going in the cache block of Test class. I want to get the Response which is created using the myException ExceptionHandler & test its response code. Can anyone tell me how to do it using Mockito?


Answer:

You can use the expected attribute, but if you need to test for some particular message, try something like this:

 @Test
  public void shouldThrowSomeException() {
        String errorMessage = "";
        try {
            Result result = service.method("argument");
        } catch (SomeException e) {
            errorMessage = e.getMessage();
        }
        assertTrue(errorMessage.trim().equals(
                "ExpectedMessage"));
  }

Question:

I faced with a problem when try to use BDD approach with scalatest and mockito. To reduce code duplication I put each needed when() rule inside each of describe blocks. But I was surprised by the ordering how describe() blocks run.

class SomeTest extends FunSpec with BeforeAndAfterAll with MockitoSugar {

  private val catalogClient = mock[CatalogServiceClient]

  override def beforeAll {
      when(catalogClient.getFrame(any)).thenReturn(Frame())
  }

  describe("MyTest1") {
    println("Inside MyTest1")

    when(catalogClient.getConnection(any))
      .thenReturn(Conn(ID_FOR_TEST_1))

    it("should perform action with data ID_FOR_TEST_1") {
      println("Inside it 1")
    }

    it("should perform another action with data ID_FOR_TEST_1") {
      ///
    }

  }

  describe("MyTest2") {
    println("Inside MyTest2")

    when(catalogClient.getConnection(any))
      .thenReturn(Conn(ID_FOR_TEST_2))

    it("should perform logic with data ID_FOR_TEST_2") {
      println("Inside it 2")
    }

    it("should perform another logic with data ID_FOR_TEST_2") {
      ///
    }
  }
}

It printed:

"Inside MyTest1"
"Inside MyTest2"
"Inside it 1"
"Inside it 2"

while I was expecting

"Inside MyTest1"
"Inside it 1"
"Inside MyTest2"
"Inside it 2"

And the first test failed because mocked data replaced in the second describe() block.

So it firstly goes through all describe blocks and after that run the tests.

After some researching, I found path.FunSpec class that preserves ordering of each describe block, but it doesn’t allow use traits like BeforeAndAfter because of overriding runTest() method as final.

I would like to know some good practices to organise such tests with minimum code duplication. And some recommendations about my particular case.


Answer:

By default, scalatest runs the tests in parallel to make the test time shorter.

The fact that you have this problem points to another problem you have, and have fortunately stumbled upon - your tests are not isolated.

To solve the problem, have each test create its own version of the mocked object. If you want to reduce code duplication, scalatest has hooks that can run code before every test.

Question:

I'm trying to mock a RestTemplate exchange() call with the following code:

Test method

given(restTemplate.exchange(any(UriComponents.class), any(HttpMethod.class), any(HttpEntity.class), any(StatusResponse.class)))
            .willReturn(new ResponseEntity<>(HttpStatus.BAD_GATEWAY));

The code does not compile because:

  1. it complains that cannot resolve method willReturn(new ResponseEntity<>(HttpStatus.BAD_GATEWAY))
  2. it complains that cannot resolve method exchange(T, T, T, T)

How should I change the signature to make it work? Thanks.


Answer:

Take a look at docs at the exchange methods. I don't see any method which uses UriComponents in arguments.

As the first argument of exchange method you need to use String , URI or RequestEntity