3

I writing a unit test for one of my validators which use an Integer type as an @Autowired dependency.

Now, while writing test I am not able to @Mock it as Spring says -

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class java.lang.Integer
Mockito cannot mock/spy following:
  - final classes
  - anonymous classes
  - primitive types

How should I get around it?

My validator looks like this-

public class MyValidator {

    @Autowired
    @Qualifier(value = "intervalInDays")
    private Integer intervalInDays; // does not get mocked!!

    @Autowired
    private LanguageValidator languageValidator;

    @Autowired
    private IdValidator idValidator;

    public void validate(Request request) {
     //does some validations

    }
}

The test for this validator class looks like this-

@RunWith(MockitoJUnitRunner.class)
public class MyValidatorTest {

    @InjectMocks
    private MyValidator myValidator; //isnt mocked at all

    @Mock
    private LanguageValidator languageValidator; //works fine

    @Mock
    private IdValidator idValidator; //works fine

    @Mock(name = "intervalInDays")
    private Integer intervalInDays;

//some tests here
}

Please suggest a solution as the intervalInDays fails to mock citing the reason stated above for Mockito.

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
Vishal
  • 666
  • 1
  • 8
  • 30

2 Answers2

0

Why don't you just create a setter for this attribute?

Furthermore you could create a Constructor for MyValidator and inject the Autowired attributes there. This makes testing even more easy.

Example:

public class MyValidator {

@Autowired
public MyValidator(Integer intervalInDays, LanguageValidator languageValidator, IdValidator idValidator) {
//Set your global attributes
}
}

Here it's explained why @InjectMock is not really a good practice.

questionaire
  • 2,475
  • 2
  • 14
  • 28
  • 1
    If just for test, I have to provide a setter than why will I use Autowiring? Its like I am giving two ways for the dependency to be set. – Vishal Jul 12 '16 at 04:45
  • First you could make your setter only package visible. Second, it's about to make your code testable more easy. Actually I never used `@InjectMocks` since I wrote my code like, that I can inject my properties. Third you can still go for the constructor. – questionaire Jul 12 '16 at 04:48
  • Furthermore here http://stackoverflow.com/questions/2457239/injecting-mockito-mocks-into-a-spring-bean?rq=1 you can see many ways on how to inject mocks.. – questionaire Jul 12 '16 at 05:01
  • Please check this http://stackoverflow.com/questions/38265075/mockito-limitations/38265333#38265333 – Gangadhar Jul 12 '16 at 06:37
  • Thats bad if that is the only solution as it is not consistent with the way spring deals with other dependencies. – Vishal Jul 12 '16 at 07:12
  • 1
    Why would I make a setter when I already have a constructor? – wilmol Sep 06 '20 at 23:42
  • Agreed with @wilmol adding a setter to a constructor make no sense. Sadly, this doesn't answer the question, just make a workaround. – P. Waksman Oct 04 '21 at 15:02
  • I don't why you're trying to inject variable. Sometimes you can't control external classes and thet don't have any set method. In that case what I've done is to use When() method from mockito tochange the behavior of that – Erick Jhorman Romero Aug 04 '23 at 20:04
0

What your test is telling you is you should change your code. if you have neither setter nor constructor. You can change the behavior of the set doing this.

Mockito.when(YourClass.setProperty().thenReturn("anything");