Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@InjectMocks on a class that has primitives as fields

Tags:

java

mockito

Here's my class I'm trying to mock.

private MemcachedClient memcachedClient;

private CachedObjectFactory cachedObjectFactory;

private int cacheTimeToLive;

private boolean hasCert;

@Autowired
public MyClass(CachedObjectFactory cachedObjectFactory,
                         MemcachedClient memcachedClient,
                         @Value("${cache.ttl.in.second}") int cacheTimeToLive,
                         @Value("${hasCert}") boolean hasCert) {
    this.cachedObjectFactory = cachedObjectFactory;
    this.memcachedClient = memcachedClient;
    this.cacheTimeToLive = cacheTimeToLive;
    this.hasCert = hasCert;
}

When I use @InjectMocks, it complains that it can't figure out how to initialize it with a default constructor (because there isn't one). I think mockito could use create this, but I don't know how to inject a primitive (the boolean/cacheTimeToLive). Is there a way to do this in my test?

like image 975
Daniel Kaplan Avatar asked Apr 28 '16 19:04

Daniel Kaplan


People also ask

Why you should not use InjectMocks?

You shouldn't use InjectMocks to deal with injecting private fields (err..or at all) , because this kind of Dependency Injection is evil – and signals you should change your design.

What is difference between @mock and @InjectMock?

@InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock annotations into this instance. @Mock is used to create mocks that are needed to support the testing of the class to be tested. @InjectMocks is used to create class instances that need to be tested in the test class.

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.

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.


1 Answers

See Mockito documentation:

  1. Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only. If the object is successfully created with the constructor, then Mockito won't try the other strategies. Mockito has decided to no corrupt an object if it has a parametered constructor.
    Note: If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won't happen. In these cases, you will have to satisfy dependencies yourself.

[...]

And finally, no injection will happen on the type in this case:

public class ArticleManager {
    private ArticleDatabase database;
    private ArticleCalculator calculator;

    ArticleManager(ArticleObserver observer, boolean flag) {
        // observer is not declared in the test above.
        // flag is not mockable anyway
    }
}

You will have to satisfy dependencies yourself, for example with a setup method using JUnit's @Before.

like image 74
dur Avatar answered Oct 24 '22 23:10

dur