Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use @InjectMocks and initMocks() with an object that has a required String parameter?

Given a component to test that requires a non-mockable class (String) in it's constructor injection, like this:

public class MyService {     @Inject     public MyService(String param1, SomeObject param2) {             ...     } } 

I want to use Mockito to test it with a test harness like this:

public class MyServiceTests {     @Mock     private SomeObject someObject;      @InjectMocks     private MyService service;      @Before     public void setUp() {         MockitoAnnotations.initMocks(this);     } } 

Problem is, I can't @Spy or @Mock Strings (because String is a final class). So how can I use Mockito and "inject" a specific String value for the param1 argument to MyService's constructor (or otherwise test this class that requires a non-null String be passed)?

like image 937
E-Riz Avatar asked Jan 12 '16 20:01

E-Riz


People also ask

Can we use @SPY and @InjectMocks together?

@Spy and @InjectMocks cannot be used well together (see Google Code issue #489 and GitHub issue #169), and for what they do it is not clear or common that they should be used together at all. In well-written Mockito usage, you generally should not even want to apply them to the same object.

Can we use InjectMocks and Autowired together?

Here if you see @Autowired @InjectMocks are used together and what it will do is inject the mocked class (which is SomeRepository in our case) and Autowired annotation adds any other dependency which the class might have. The last thing you need to do is create a Setter for SomeRepository object in your actual class.

What is the use of @InjectMocks annotation?

@InjectMocks is the Mockito Annotation. It allows you to mark a field on which an injection is to be performed. Injection allows you to, Enable shorthand mock and spy injections.

What can I use instead of initMocks?

initMocks. Deprecated. Use openMocks(Object) instead. This method is equivalent to openMocks(testClass).


1 Answers

I think the simple answer is not to use @InjectMocks, and instead to initialise your object directly. The only downside I can see is that you're not testing the injection, but then with @InjectMocks, I think you'd be testing it with Mockito's injection implementation, rather than your real framework's implementation anyway, so no real difference.

I'd do:

public class MyServiceTests {   @Mock   private SomeObject someObject;    private MyService service;    @Before   public void setUp() {     service = new MyService("foo", someObject);   } } 
like image 114
DaveyDaveDave Avatar answered Oct 17 '22 04:10

DaveyDaveDave