Mockito: mocked object not injected on constructor argument - java

I've this constructor:
public class AuditsLoaderService {
public AuditsLoaderService(
BackOfficeProperties backOfficeProperties,
FrontOfficeInterfaceService frontOfficeService,
AuditService auditService,
I18nResourceBundleMessageSource messageSource,
MonitorService monitor
) {
// some code
}
}
and AuditService is:
public class AuditService {
public AuditService(
BackOfficeProperties backOfficeProperties,
AuditFactory auditFactory,
AuditDao auditDAO,
RedisDao auditRedisDao,
ObjectMapper objectMapper,
I18nResourceBundleMessageSource messageSource
) {
Into my test:
#RunWith(MockitoJUnitRunner.class)
public class MalformedAuditsTest {
#Mock
private BackOfficeProperties backOfficeProperties;
#Mock
private AuditFactory auditFactory;
#Mock
private AuditDao auditDao;
#Mock
private RedisDao redisDao;
#Mock
private ObjectMapper objectMapper;
#Mock
private I18nResourceBundleMessageSource i18nResourceBundleMessageSource;
#Mock
private MonitorService monitorService;
#InjectMocks
#Spy
private AuditService auditService;
#InjectMocks
private FrontOfficeInterfaceService frontOfficeService;
#InjectMocks
private AuditsLoaderService auditsLoaderService;
}
Nevertheless, I'm getting an NulPointerException inside my AuditsLoaderService since auditService is null.
It seems it's not injected.
I've annotated it as:
#InjectMocks
#Spy
private AuditService auditService;
Should I add some more code/annotation?
EDIT
I've just realized neither frontOfficeService neither auditSerice are injected on.
So, it seems all #InjectMocks fields are not injected on others ones

Try adding:
#Mock
private ObjectMapper objectMapper;
because your AuditService constructor requires it
EDIT: It's probably easier to create objects manually by passing mocks in corresponding constructor

Related

How to Mock service consisting both Autowired and RequiredArgsConstructor in JUnit 5?

#RequiredArgsConstructor
public class GService {
#Autowired
private GRepository repository;
private final List<GRule> rules;
And my test class is like this;
#ExtendWith(MockitoExtension.class)
class GServiceTest {
#InjectMocks
private GService service;
#Mock
private GRepository repository;
#Mock
private List<GameRule> rules;
Rules is okay but repository is not initialized and it is null. How can I initialize the repository?
You can set by using ReflectionTestUtils.setField(...) in Before Method;
ReflectionTestUtils.setField(service, "repository", Mockito.mock(GRepository.class));

How to mock class with #ConfigurationProperties in Spring Boot

I have a class that Autowires another class with #ConfigurationProperties.
Class with #ConfigurationProperties
#ConfigurationProperties(prefix = "report")
public class SomeProperties {
private String property1;
private String property2;
...
Class that Autowires above class SomeProperties
#Service
#Transactional
public class SomeService {
....
#Autowired
private SomeProperties someProperties;
.... // There are other things
Now, I want to test SomeService class and in my test class when I mock SomeProperties class, I am getting null value for all the properties.
Test class
#RunWith(SpringRunner.class)
#SpringBootTest(classes = SomeProperties.class)
#ActiveProfiles("test")
#EnableConfigurationProperties
public class SomeServiceTest {
#InjectMocks
private SomeService someService;
#Mock // I tried #MockBean as well, it did not work
private SomeProperties someProperties;
How can I mock SomeProperties having properties from application-test.properties file.
You are not mocking SomeProperties if you intend to bind values from a properties file, in which case an actual instance of SomeProperties would be provided.
Mock:
#RunWith(MockitoJUnitRunner.class)
public class SomeServiceTest {
#InjectMocks
private SomeService someService;
#Mock
private SomeProperties someProperties;
#Test
public void foo() {
// you need to provide a return behavior whenever someProperties methods/props are invoked in someService
when(someProperties.getProperty1()).thenReturn(...)
}
No Mock (someProperties is an real object that binds its values from some propertysource):
#RunWith(SpringRunner.class)
#EnableConfigurationProperties(SomeConfig.class)
#TestPropertySource("classpath:application-test.properties")
public class SomeServiceTest {
private SomeService someService;
#Autowired
private SomeProperties someProperties;
#Before
public void setup() {
someService = new someService(someProperties); // Constructor Injection
}
...
You need to stub all the property values in #Test/#Before methods of SomeServiceTest.java like :
ReflectionTestUtils.setField(someProperties, "property1", "value1");
ReflectionTestUtils.setField(object, name, value);
You can also mock the reponse for dependent classes via Mockito.when()
If you are using #Mock , you need to stub the values as well. By default the value will be null for all the properties.

Mocking #Resource when using MockMvcBuilders.standaloneSetup

My team is currently building a SpringBoot API. Below is a snippet of how my team is mocking for our controller tests. This works when we have plain classes as dependencies.
#RunWith(SpringRunner.class)
#SpringBootTest
public class TestController {
private MockMvc mockMvc;
#Mock
private MyService myService;
#Autowired
#InjectMocks
private MyController myController;
#Before
public void setup() {
//Build the controller mock handler
mockMvc = MockMvcBuilders
.standaloneSetup(myController)
.build();
}
We cannot figure out how to mock a #Resource like below for a similar test.
#Resource(name = "domainNameToCode")
private Map<String, Integer> domainCodes;
As the domainCodes is private your controller needs to have a way to set value for it either constructor or a setter.
Setter
#Autowired()
#Qualifier("domainNameToCode")
public void setDomainCodes(Map<String, Integer> domainCodes) {
...
}
Constructor
#Autowired()
#Qualifier("domainNameToCode")
public MyController(Map<String, Integer> domainCodes){
}
In your tests, now you can inject the mocks.
If you don't want to edit your source, then you can use reflection to set a private instance variable on an object
//Using reflection to set a private field on an object
FieldUtils.writeField(controllerInstance, "domainCodes", new HashMap<>()) ;

Mockito - how to inject final field marked as #Mock by constructor when using #Spy and #InjectMocks

I have a special case, where I have to mock some fields and use both #Mock and #Spy for my class, which is under test, because at some tests I need to change behaviour of it's own methods. I use #InjectMocks for constructor. It looks like this:
Test class:
#RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
#Mock
private SomeObject usedAsNonFinal;
#Mock
private SomeObject usedAsFinal;
#Spy
#InjectMocks
private ServiceTest service = new ServiceTest(usedAsNonFinal, usedAsFinal);
#Before
public void setup() {
when(usedAsNonFinal.someMethod(Matchers.any()))
.thenReturn(someObject);
when(usedAsFinal.someMethod(Matchers.any()))
.thenReturn(someObject);
doReturn(someObject).when(service).someMethod(Matchers.any());
}
}
Service, which is under test:
#Service
public class Service {
private SomeObject usedAsNonFinal //injects correctly
private final SomeObject usedAsFinal; //null - not injected
#Autowired
public Service (SomeObject usedAsNonFinal, SomeObject usedAsFinal){
this.usedAsNonFinal = usedAsNonFinal;
this.usedAsFinal = usedAsFinal;
}
//some methods to mock depending on test
}
The problem is - as commented in code - that final field is not getting injected and it's null. When I remove final keyword it gets injected correctly and all tests are working as expected. I tried some tricks from other topics - also using reflection, but nothing seems to be workking in this particular case.
Did you try don't instantiate ServiceTest in test?
#InjectMocks should do it for you. Try just
#Spy
#InjectMocks
private ServiceTest service;

How to tell Mockito to use real (unmocked) version of a helper class?

With Mockito, I'm used to injecting Mocks into a single class-under-test as follows:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest() {
#InjectMocks
private MyClass myClass;
#Mock
private OtherClass1 mockedClass1UsedByMyClass;
#Mock
private OtherClass2 mockedClass2UsedByMyClass;
But let's say MyClass also uses a simple class HelperClass, which provides some simple "helper" methods and doesn't have any further dependencies:
public class MyClass {
#Autowired
private OtherClass1 otherClass1;
#Autowired
private OtherClass2 otherClass2;
#Autowired
private HelperClass helperClass; // Don't want to mock this one...
Would rather use the real version of this class rather than trying to mock out everything being returned as all it's doing is some simple, deterministic processing. Is there a way of doing this?
If you want to take advantage of the #InjectMocks then use a #Spy.. by default it will use original impl and you can hand-pick the methods you want to mock:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest() {
#InjectMocks
private MyClass myClass;
#Mock
private OtherClass1 mockedClass1UsedByMyClass;
#Spy
private HelperClass helperClass;
#Mock
private OtherClass2 mockedClass2UsedByMyClass;
}

Categories

Resources