Injecting a mock into an @Autowired field in TestNG

5,566 views
Skip to first unread message

Adam Gordon

unread,
Aug 9, 2012, 11:52:42 AM8/9/12
to moc...@googlegroups.com
From what I can glean from the web, this should be possible.

I have a Spring @Service I want to test and I want to inject a mocked member into this service.  Here's the code snippet:

@Service
public class FooService {

 ...

  public void doSomethingWithBar() {

    this.bar.doSomething();
  }

  @Autowired
  private Bar bar;
}

And here's my test class snippet:

@ContextConfiguration(locations = "/test-application-config.xml")
@Listeners(MockitoTestNGListener.class)
public class FooServiceTest extends AbstractTestNGSpringContextTests {

  ...

  @Mock
  private Bar bar;

  @InjectMocks
  @Autowired
  private FooService fooService;
}

What's happening in the test is that the actual implementation of Bar.doSomething() is being executed instead of a mocked method.  What am I doing wrong here?  Is the @Autowired messing things up?

Thanks,

--adam

Wesley Lira

unread,
Aug 9, 2012, 5:25:21 PM8/9/12
to moc...@googlegroups.com
Hi Adam.

I don't know how @Mock works with TestNG, but using JUnit, it just works with @RunWith(MockitoJUnitRunner.class).
If you don't use a MockitoRunner class, the mocks would not be injected.

Using spring, you should use springockito, that allow you to declare mocks in your applicationContext.xml, then spring injects the mock normally with @Autowired.
I've already used it. It works fine!

Wujek Srujek

unread,
Aug 10, 2012, 2:36:08 AM8/10/12
to moc...@googlegroups.com
The easiest thing would be to ditch field injection and use constructor / method injection. There are many many people that consider field injection bad practice, as it is not well testable, as you are just experiencing. Of course, you can use springmockito and define the mocks there, but then again, this is no unit test any more, at least in my vocabulary, as you depend on some additional services, like the spring container.

wujek

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To view this discussion on the web visit https://groups.google.com/d/msg/mockito/-/z5eLRSYoWqIJ.
To post to this group, send email to moc...@googlegroups.com.
To unsubscribe from this group, send email to mockito+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mockito?hl=en.

Eric Lefevre-Ardant

unread,
Aug 10, 2012, 4:09:08 AM8/10/12
to moc...@googlegroups.com
I agree 100% with Wujek.
I might add that having to pass dependencies to a constructor tend to make us feel the pain when there are too many dependencies, which is a strong sign that the class under test should be split.

Russell Bateman

unread,
Aug 10, 2012, 9:10:43 AM8/10/12
to moc...@googlegroups.com
I do this and the only way I could ever get it to work, even with Spring, was to hand-inject it. No, I didn't like having to put the injection method into FooService. I didn't and still don't know anything about @InjectMocks. There may be a better answer.
...
FooService service;
@Mock private Bar bar;

@Before public void setup()
{
    ...
    service = new FooService();
    service.setBar( bar );
}

Adam Gordon

unread,
Aug 10, 2012, 1:14:03 PM8/10/12
to moc...@googlegroups.com
I've used Springockito and while I do like it, it unfortunately requires you to define your beans in XML rather than by using class annotations (i.e. @Component).

That said, ultimately, I just went with this solution.  Thanks.

Adam Gordon

unread,
Aug 10, 2012, 1:16:12 PM8/10/12
to moc...@googlegroups.com
I think I have to agree.  For me, it's not the pain of constructor parameters, rather it's the extra setters one has to add to classes to add the dependencies.  I suspect I'm just being lazy but one line of code is easier/cleaner than three...but at the expense of testability.

Brice Dutheil

unread,
Aug 20, 2012, 9:07:50 AM8/20/12
to moc...@googlegroups.com
Hi Adam,

I believe the Spring TestNG integration overrides what is done in the listeners, unfortunately this is not really possible to order the execution of the Listeners in TestNG.

Also I agree with Wujek, InjectMocks was made to ease mock injection. However, I strongly advise to not mix @InjectMocks and Spring in unit tests. Besides it wouldn't be unit tests anymore then, but integration tests.

Cheers,
-- Brice



To view this discussion on the web visit https://groups.google.com/d/msg/mockito/-/L_EOAEe5StQJ.
Reply all
Reply to author
Forward
0 new messages