Showing posts with label Mocks. Show all posts
Showing posts with label Mocks. Show all posts

Friday, August 9, 2013

Injecting Test Doubles in Spring using Mockito and BeanPostProcessors


I'm pretty sure that if you have ever used Spring and are familliar with unit testing, you have encountered a problem related to injecting mocks / spies (Test Doubles) in the Spring's application context which you wouldn't want to modify. This article presents an approach how to solve this issue using Spring's components.

Tuesday, August 6, 2013

Spock - return nested spies / mocks


Hi! Some time ago I have written an article about Mockito and using RETURNS_DEEP_STUBS when working with JAXB. Quite recently we have faced a similliar issue with deeply nesetd JAXB and the awesome testing framework written in Groovy called Spock. Natively Spock does not support creating deep stubs or spies so we needed to create a workaround for it and this article will show you how to do it.

Wednesday, October 24, 2012

Mockito InvocationOnMock - checking an argument



Hi!

In one of my projects we had a very interesting situation in terms of testing. We couldn't mock an invocation of a static method due to the fact that PowerMock was not allowed to be used so there were plenty of objects and dependencies being initialized. What is more we were using a custom made dependency injection system that had a possibility of injecting a mock.

The problem was such that during a test we wanted to assert whether one of the objects was in a very precise state. This object was created using the new operator so we couldn't mock it (again no PowerMock allowed). Fortunately this object got passed to a method of an object that we could mock...

As presented below timeConsumingExternalService is an object that we could mock via the custom dependency injection system whereas the SomePojo class is an object whose state we would like to verify.

timeConsumingExternalService.processSomeObject(new SomePojo("name", "surname", 1, 1.0));

So what we did was that in our mock to which the object got passed we created a new Answer (the same Answer that I spoke of here). Due to which we could access the InvocationOnMock and the arguments passed to the method as such.

Mockito.doAnswer(new Answer<Object>() {
   public Object answer(InvocationOnMock invocation) throws Throwable {
    Object[] object = invocation.getArguments();

      if (object.length > 0) {
          SomePojo somePojo = (SomePojo) object[0];

          Assert.assertEquals("name", somePojo.getName());
          LOGGER.debug("Names are equal");
          Assert.assertEquals("surname", somePojo.getSurname());
          LOGGER.debug("Surnames are equal");
          Assert.assertTrue(1 == somePojo.getIntValue());
          LOGGER.debug("Ints are equal");
          Assert.assertTrue(1.0 == somePojo.getDoubleValue());
          LOGGER.debug("Doubles are equal");

          LOGGER.debug("Object being an argument of the function [" + String.valueOf(somePojo) + "]");
  }
    return null;
   }
  }).when(timeConsumingExternalServiceMock).processSomeObject(Mockito.any(SomePojo.class));

Of course the logs regarding the equalities are unnecessary since if they wouldn't be equal we would have an assertion exception - I left them for the purpose of this post.

And in the logs we can find:

pl.grzejszczak.marcin.ServiceIntegrationTest:48 Names are equal
pl.grzejszczak.marcin.ServiceIntegrationTest:50 Surnames are equal
pl.grzejszczak.marcin.ServiceIntegrationTest:52 Ints are equal
pl.grzejszczak.marcin.ServiceIntegrationTest:54 Doubles are equal
pl.grzejszczak.marcin.ServiceIntegrationTest:56 Object being an argument of the function [SomePojo [name=name, surname=surname, intValue=1, doubleValue=1.0]]

So in this way something that seems impossible to be verified can get verified :)

Update!

Thanks to Holger's suggestion I took a look at the ArgumentCaptor object and that is true that it is an elegant solution to retrieve information about the arguments executed on a method. Where InvocationOnMock can give you much more information and possibilities (for instance regarding the method being executed or just execute the real method) for this particular case a much more elegant, easier and faster way of dealing with the issue would be:


  //service that executes the external service
  executorService.execute(someTask);

  final ArgumentCaptor<SomePojo> argumentCaptor = ArgumentCaptor.forClass(SomePojo.class);
  Mockito.verify(timeConsumingExternalServiceMock).processSomeObject(argumentCaptor.capture());
  SomePojo somePojo = argumentCaptor.getValue();
  Assert.assertEquals("name", somePojo.getName());
  LOGGER.debug("Names are equal");
  Assert.assertEquals("surname", somePojo.getSurname());
  LOGGER.debug("Surnames are equal");
  Assert.assertTrue(1 == somePojo.getIntValue());
  LOGGER.debug("Ints are equal");
  Assert.assertTrue(1.0 == somePojo.getDoubleValue());
  LOGGER.debug("Doubles are equal");

The logs:
pl.grzejszczak.marcin.junit.SomeTask:26 Before processing an object
pl.grzejszczak.marcin.junit.SomeTask:28 After processing an object
pl.grzejszczak.marcin.ServiceIntegrationTest:75 Names are equal
pl.grzejszczak.marcin.ServiceIntegrationTest:77 Surnames are equal
pl.grzejszczak.marcin.ServiceIntegrationTest:79 Ints are equal
pl.grzejszczak.marcin.ServiceIntegrationTest:81 Doubles are equal

Thanks again Holger!