when I run the test case I get AnObj mocked. this is used from inside the target classes method. when that method gets invoked the 'anOtherObj' is accessed and that is found to be null. Can some one please point out how to make sure 'anOtherObj' is not null so that I dont get nullpointer there?
#Test
public class TestTargetTest {
#Mock
private AnObj anObj;
#InjectMocks
private TestTarget testTarget;
#BeforeMethod
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testTarget() {
when(anObj.someMethod()).thenCallRealMethod();
testTarget.testTarget();
}
}
#Component
public class TestTarget {
#Autowired
private AnObj anObj;
public void testTarget(){
anObj.someMethod();
}
}
#Component
public class AnObj {
#Autowired
private AnOtherObj anOtherObj;
public void someMethod(){
syso(anOtherObj.toString());
}
}
You need to initialize annotated mocks in your test class.
#BeforeMethod
public void beforeClass() {
MockitoAnnotations.initMocks(this);
}
Why would you care what's inside mock (AnObj)? I assume you haven't yet declared interactions on that mock using Mockito.when.
As mentioned by #Valya that point was valid. I shouldn't have mocked that. I needed to autowire 'AnObj'. Thanks a lot for all the help. It made the difference.
Related
I am doing a migration from Spring 4.x to 5.x and am following the recommendation to wrap the object with an ObjectProvider to handle beans that return null: https://stackoverflow.com/a/49393682/10863988
This is the class set up I have:
class ConfigurationClass{
#Autowired
private ObjectProvider<MyObject> myObject;
public SomeOtherClass getSomeOtherClass() {
return new SomeOtherClass(myObject.getIfAvailable());
}
}
class TestSomeOtherClass {
#Mock
MyObject myObject;
#InjectMocks
ConfigurationClass;
SomeOtherClass someOtherClass;
public void setup() {
this.someOtherClass = spy(configuration.getSomeOtherClass());
}
}
The problem is when I run this test. the myObject in the ConfigurationClass returns a null pointer exception.
I've tried adding this to the TestSomeOtherClass but I still can't seem to mock the ObjectProvider<MyObject>:
class TestSomeOtherClass {
#Mock
MyObject myObject;
#Mock
ObjectProvider<MyObject> myObjectObjectProvider;
#InjectMocks
ConfigurationClass;
SomeOtherClass someOtherClass;
public void setup() {
doReturn(myObject).when(myObjectObjectProvider).getIfAvailable();
this.someOtherClass = spy(configuration.getSomeOtherClass());
}
}
Any advice on how to handle this?
You do not tell Mockito to handle it's annotations (#Mock, #InjectMocks) anywhere in your code, so they do not have any effect. By default all non-primitive fields in Java are initialized as null - that's where the NullPointerException comes from.
openMocks/initMocks method
Depending on the version of Mockito you're using, you need to call initMocks() or openMocks() static method from the MockitoAnnotations class:
AutoCloseable openMocks;
#BeforeEach
public void setup() {
// the line below is where the magic happens
openMocks = MockitoAnnotations.openMocks(this);
doReturn(myObject).when(myObjectObjectProvider)
.getIfAvailable();
someOtherClass = spy(configuration.getSomeOtherClass());
}
#AfterEach
void tearDown() throws Exception {
openMocks.close();
}
#Test
void test() {
assertNotNull(someOtherClass);
}
#ExtendWith(MockitoExtension.class)
You can also use the #ExtendWith(MockitoExtension.class) annotation over your class and it has the same effect as the methods described above.
You can find both approaches tested in a GitHub repository I've created (all tests pass).
I have a dummy project where I try figure out how to test pointcuts being triggered.
My project consists of 1 aspect bean which just prints after a foo method is called
#Component
#Aspect
public class SystemArchitecture {
#After("execution(* foo(..))")
public void after() {
System.out.println("#After");
}
}
And a FooServiceImpl with implemented foo method
#Service
public class FooServiceImpl implements FooService{
#Override
public FooDto foo(String msg) {
return new FooDto(msg);
}
}
The code works and and I can see "#After" being printed to console, but I can't check programatically if after pointcut was called using the test below.
#SpringBootTest
public class AspectTest {
#Autowired
private FooService fooService;
#Test
void shouldPass() {
fooService.foo("hello");
}
}
I've also tried using non-bean proxy as was adviced in https://stackoverflow.com/a/56312984/18224588, but this time I'm getting an obvious error cannot extend concrete aspect because my spy proxy is no longer viewed as an aspect:
public class AspectNoContextTest {
#Test
void shouldPass() {
FooService fooService = Mockito.mock(FooService.class);
SystemArchitecture systemArchitecture = Mockito.spy(new SystemArchitecture());
AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(fooService);
aspectJProxyFactory.addAspect(systemArchitecture);
DefaultAopProxyFactory proxyFactory = new DefaultAopProxyFactory();
AopProxy aopProxy = proxyFactory.createAopProxy(aspectJProxyFactory);
FooService proxy = (FooService) aopProxy.getProxy();
proxy.foo("foo");
verify(systemArchitecture, times(1)).after();
}
}
Ok, after some digging, I found that it's possible to accomplish this by making an aspect a #SpyBean. Also AopUtils can be used for performing additional checks
#SpringBootTest
public class AspectTest {
#Autowired
private FooService fooService;
#SpyBean
private SystemArchitecture systemArchitecture;
#Test
void shouldPass() {
assertTrue(AopUtils.isAopProxy(fooService));
assertTrue(AopUtils.isCglibProxy(fooService));
fooService.foo("foo");
verify(systemArchitecture, times(1)).after();
}
}
I have the following Spring Service class that I'm trying to test with Mockito:
#Service
public class ObjectExportService {
#Autowired
protected List<SecuredService<? extends SecuredObject>> securedServices;
public void doStuff() {
for(int i = 0; i < this.securedServices.size(); i++){
SecuredService<? extends SecuredObject> securedSrv = this.securedServices.get(i);
//this access works
}
for (SecuredService<? extends SecuredObject> securedSrv : this.securedServices) { //this access does not work
}
}
}
This is my Test class for that service:
#RunWith(MockitoJUnitRunner.class)
public class ObjectExportServiceTest {
#InjectMocks
private ObjectExportService objectExportService;
#Mock
protected List<SecuredService<? extends SecuredObject>> securedServices;
#Test
public void testDoStuff(){
objectExportService.doStuff();
Assert.assertTrue(true);
}
}
When I run the test, I get a NullpointerException, but only in the for-each loop.
First I assumed is a similar problem as described in this thread:
I have Mocked the List and would therefore need to mock the iterator() call.
The solutions provided in that thread didn't work for me, because I am actually autowiring a List.
So I stumbled across this solution in another thread. Simply changing the #Mock to #Spy resolved the issue for me:
#RunWith(MockitoJUnitRunner.class)
public class ObjectExportServiceTest {
#InjectMocks
private ObjectExportService objectExportService;
#Spy // <-- change here
protected List<SecuredService<? extends SecuredObject>> securedServices;
#Test
public void testDoStuff(){
objectExportService.doStuff();
Assert.assertTrue(true);
}
}
I'm getting a Null Pointer Exception as shown in the code when I run the following Junit test. Can someone please help me fix it?
import com.apexsct.pouservice.amq.inboxlistener.GetUpdateAvailablePositionInfo;
import com.apexsct.servcomm.amq.pouservice.dto.DeliveryPositionData;
public class GetUpdateAvailablePositionInfoActionTest {
#Mock
protected PositionRepository positionRepo;
#Mock
protected UserInterfaceGroupRepository uiGroupRepo;
#InjectMocks
private GetUpdateAvailablePositionInfo service;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testEmptyRequest() {
DeliveryPositionData response = (DeliveryPositionData) service.perform(); // NULL POINTER EXCEPTION HERE
assertEquals(ErrorMessageConstant.INVALID_REQUEST, response.getErrMsg());
}
}
Based on your test name you want to test a case where the request is empty.
However you still need to supply an actual object, as your code does not
handle the case where request is null.
You could adjust the test to look like this:
public class GetUpdateAvailablePositionInfoActionTest {
#Mock
protected PositionRepository positionRepo;
#Mock
protected UserInterfaceGroupRepository uiGroupRepo;
#Mock // creates and injects a mock for the request
UpdAvlbPosRequest request;
#InjectMocks
private GetUpdateAvailablePositionInfo service;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testEmptyRequest() {
// defines that the sn of the request is an empty string
// (Depending on what StringUtils class you use, it might also handle null correctly.
// In this case this line can be removed)
Mockito.when(request.getSn()).thenReturn("");
DeliveryPositionData response = (DeliveryPositionData) service.perform();
assertEquals(ErrorMessageConstant.INVALID_REQUEST, response.getErrMsg());
}
}
consider my scenario
public class SomeClass {
#Autowired #Qualifier("converter1") private IConverter converter1;
#Autowired #Qualifier("converter2") private IConverter converter2;
public void doSomeAction(String mimeType) {
converter1.execute();
converter2.execute();
}
}
This is my code.
In order to test this
#RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
#Mock(name="converter1") IConverter converter1;
#Mock(name="converter2") IConverter converter2;
#InjectMocks SomeClass class = new SomeClass();
#Test
public void testGetListOfExcelConverters() throws Exception {
class.doSomeAction("abcd");
}
}
Here the mocks are not getting injected, please help with the proper mechanism for mocking a qualified beans.
If this is not the right way to code using spring, please let me know the correct method for using this.
Not sure what error you are getting, but your test class doesn't compile because you have what looks like you intend to be a variable name using the keyword class. This worked for me:
#RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
#Mock(name="converter1") IConverter converter1;
#Mock(name="converter2") IConverter converter2;
#InjectMocks
SomeClass clazz = new SomeClass();
#Test
public void testGetListOfExcelConverters() throws Exception {
clazz.doSomeAction("abcd");
verify(converter1).execute();
verify(converter2).execute();
}
}
And by "worked for me" I mean that the test actually ran and passed. Note I added a couple of verify statements to assert that the injected mocks got called.
I used the SomeClass code you provided as-is.
For me, both existing answers were insufficient.
#riddy 's answer did not take into account different test cases.
#jhericks ' answer did not use the Spring context, which caused other issues down the line.
Here's my solution:
#MockBean
#Qualifier("myNamedBean")
private SomeBean someBean;
As simple as that.
You can mock beans using a test configuration:
#Configuration
public class TestConfig {
#Bean
public MyService myService() {
return Mockito.mock( MyService.class );
}
}
I've found this solution:
#RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
#Mock()
#Qualifier("converter1")
IConverter converter1;
#Mock()
#Qualifier("converter1")
IConverter converter2;
#InjectMocks SomeClassTest testObj = new SomeClassTest();
#Test
public void testGetListOfExcelConverters() throws Exception {
testObj.doSomeAction("abcd");
verify(converter1).execute();
verify(converter2).execute();
}
}
BTW, I haven't found this in doc.
In my app, the #Autowired beans are passed as constructor args. None of the variations (albeit JUnit 5 version) were working. Instead, I had to "kick it old school" and simply instantiate the mocks directly.
public class SomeClass {
private final IConverter converter1;
private final IConverter converter2;
public SomemClass( #Autowired #Qualifier("converter1") conv1,
#Autowired #Qualifier("converter2") conv2 ) {
this.converter1 = conv1;
this.converter2 = conv2;
}
public void doSomeAction(String mimeType) {
converter1.execute();
converter2.execute();
}
}
public class SomeClassTest {
IConverter converter1;
IConverter converter2;
SomeClass pojo;
#BeforeEach
public void setup() {
converter1 = Mockito.mock( IConverter.class );
converter2 = Mockito.mock( IConverter.class );
pojo = new SomeClass( converter1, converter2 );
}
#Test
public void testGetListOfExcelConverters() throws Exception {
pojo.doSomeAction("abcd");
}
}