Why i am getting null value when i am mocking or Inject the object .? - spring

I am getting a null value when i am trying to Inject the Dao interface.
Sample of code here when i am writing a test cases.
#Mock
private ServiceUriLocator serviceLocator;
#Mock
private SessionDao sessionDao;
ActiveSession session;
AccountData accountdata;
#InjectMocks
Account account
This Above code when i am using inside Method like
#Test
public void testActivate()
{
Response response=account.activate(accountdata).
}
private Accountdata accountdata(){
accountdata.setFirstName("Employee_name");
accountdata.LastName("Employee_Last_Name");
return accountdata;
}
In above code account value is null that's why i am getting null pointer exception.
Anybody can calrify why i am getting null value for injecting the mock value.

There are many factors while executing a test case using mock frameworks.
Is Runner setup ? Which runner are you executing with?
It has to be MockitoJunitRunner that helps to run with Mocks
when statement is written on the same mock object ?
This has to match with same mock object
Is the input string/data match the when statement ?
This has to be same input
when(service.execute('hi')).thenReturn();
is different from
when(service.execute('hello')).thenReturn();
Where is the when written ? setup - #Before level or test method level ?
The Global statements written applies to all the test methods, so be careful while you make the when statements in the #Before method.
These are some of the debug points.

Related

unable to mock crudrepository save method

#ExtendWith(MockitoExtension.class)
class taskTestMain {
#InjectMocks
task task1;
#Mock
private statusRepository statusRepo;
#Mock
status statusRec;
#Test
void test() {
Mockito.when(statusRepo.save(statusRec)).thenReturn(statusRec);
task1.method();
}
}
class task
{
method()
{
statusRec = statusRepo.save(statusRec); //after this step I get Potential stubbing exception
}}
I have tried several ways . I am not able to figure this out. Please suggest how to proceed. Below I have pasted the junit error. task- Strict stubbing argument mismatch. Please check:
this invocation of 'save' method:statusRepo.save(status#8bffb8b);
-> at task.run(task.java:80)
has following stubbing(s) with different arguments: 1. statusRepo.save(status#26a2f7f9
); -> at .taskTestMain.test(taskTestMain.java:110)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
Thanks for your time
To be honest I'am not totally sure about this but I have a guess.
Mockito.when(statusRepo.save(statusRec)).thenReturn(statusRec);
With this stub you simply want return the first parameter passed into the save Method? If this is true there is a more generic way to do this.
when(statusRepo.save(any(TcMdhTotemConsensusStatus.class))).then(returnsFirstArg());
This stub will always return the first argument that is passed into your save
method.
See this stackoverflow post for more information. There also some alternatives in case your Java or Mockito Version does not match.

Unit testing with MockitoJunitRunner: thenReturn always returns null for any(...) matchers

Using Spring Boot 2.1.6.RELEASE. In an unit test with MockitoJunitRunner, I'm mocking a REST controller as follows:
#Mock
private MyController myController;
Then, I'm defining the expectations of the endpoint call as follows:
when (myController.myEndpoint(any(MyInputDto.class), any(OAuth2Authentication.class))).thenReturn(new ResponseEntity<MyOutputDto>(myOutputDto, HttpStatus.OK));
But the following call:
ResponseEntity<MyOutputDto> resp = myController.myEndpoint(any(MyInputDto.class), any(OAuth2Authentication.class));
assertNotNull(resp);
raises java.lang.AssertionError as resp is null. Why is that ? Of course, the two parameters are different instances between the when(...) clause and the call (probably both null), but my understanding is that they don't have to match as I'm using any(...) matcher, meaning that whatever these instances are, the return should be the same.
What am I missing here ?
You defined your mocked object to return a new ResponseEntity when its myEndpoint method is called with two parameters: any object of type MyInputDto and any object of type OAuth2Authentication.
But when you actually call the method using
ResponseEntity<MyOutputDto> resp = myController.myEndpoint(any(MyInputDto.class), any(OAuth2Authentication.class));
you don't call it with objects of those types, but with any matchers. That case wasn't mocked, and it certainly wasn't your intention to mock matcher arguments.
Calling with actual objects instead, like
ResponseEntity<MyOutputDto> resp = myController.myEndpoint(new MyInputDto(), new OAuth2Authentication());
would work, but that would not provide what you want to achieve by running a mocked test: it would just check if the mock returns what you defined, but it would't test your controller behaviour.
What you should do instead:
Don't mock the class you want to test; mock its dependencies.
private MyController myController;
#Mock
private MyInputDto inputDto;
#Mock
private OAuth2Authentication authentication;
// mock all method calls that are needed on dependencies
when(inputDto.someMethod(...)).thenReturn(...);
[...]
when(authentication.someMethod(...)).thenReturn(...);
[...]
Now you can test the actual behaviour of your test object:
ResponseEntity<MyOutputDto> resp = myController.myEnpoint(inputDto, authentication);
assertNotNull(resp);
A nice Mockito tutorial: https://www.vogella.com/tutorials/Mockito/article.html
Mockito even hints at something being wrong when trying to implement the test like you did in your question. Running your test I get
[MockitoHint] MockitoTest.test (see javadoc for MockitoHint):
[MockitoHint] 1. Unused... -> at MockitoTest.test(MockitoTest.java:24)
[MockitoHint] ...args ok? -> at MockitoTest.test(MockitoTest.java:26)
Line 24 refers to the line where the mock was stubbed (the when(...).thenReturn() part) because it is never used; line 26 referes to the calling line because it uses Matchers instead of objects.
You should see a similar output on your console when running the test.

How to unit test a service which sets attribute to newly created object

I want to write unit test for one of my service to verify certain fields get assigned.
public void createNewRecord(Dto dto) {
Record record = new Record();
record.setName(dto.getName());
record.setDetail(dto.getDetail());
repo.save(record);
}
I don't have a constructor for dto because a record has many attributes and some of them get assigned from other methods. My previous plan is: mock the record and verify setName() and setDetail methods are called once. But there is no way to inject mocked record into this service. Do I have to change my previous code? Any thought is appreciated.
There are several approaches:
First:
change method to this
public void createNewRecord(Record record, Dao dao)
Second:
Use PowerMockito to mock constructor
Third:
Use factory or com.google.inject.Provider for construct record (I prefer this)
Forth:
If record constructor is simple and setters for record also don't have some special logic then you can mock only repo and verify repo's argument.
Mocks should be used for mocking a dependency of the tested object, not for mocking an inner object in the tested method.
Why don't you mock the repo instance and then you would verify with you mock api that repo.save() is called with the expected record ?
It seems to be a straight way to unit test your method.
You can use Mockito and its #Captor annotation to capture the arguments passed to the repo instance. You can #Mock the Dto object to create expectations for the getName() and getDetail() methods and assert that the results of invoking the setName() and setDetail() methods on the captured Record instance are the same values expected from the Dto object. For example:
#Mock
private Repo repo;
#Mock
private Dto dto;
#Captor
private ArgumentCaptor<Record> recordArgumentCaptor;
private Service service;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
this.service = new Service(repo);
}
#Test
public void shouldCreateNewRecord() {
when(dto.getName()).thenReturn("NAME");
when(dto.getDetail()).thenReturn("DETAIL");
service.createNewRecord(dto);
verify(repo).save(recordArgumentCaptor.capture());
Record record = recordArgumentCaptor.getValue();
assertThat(record.getName(), is(equalTo(dto.getName())));
assertThat(record.getDetail(), is(equalTo(dto.getDetail())));
}

Mockito Test method parameters

I have started newly working on testing using mockito. I have 2 questions ...
1. Question
I have method like below with optional and must have parameter so when I call this service method without the must params it should throw Exception.
#RequestMapping( method=RequestMethod.GET, produces={"application/xml", "application/json"})
public ResponseEntity<PResponse> get(#RequestParam(value="params1",required=false) String params1,
#RequestParam(value ="params2",required=false) String params2,
#RequestParam(value= "params3",required=true) String params3,
#RequestParam(value="refresh",required=false) boolean refresh,
#RequestParam(value="params4",required=true) List<String> params4)
{method logic ...}
Here params1,2,refresh are optional and params3,4 are must so when i get request with out params3,4 it should give an error. I am trying to write a test for this using mockito
#Test(expected = RuntimeException.class)
public void throwExceptionIfMissingParams34() throws RuntimeException {
when(myService.get(argThat(new MessagesArgumentMatcher()))).thenThrow(new RuntimeException()) ;
}
I am getting error saying get() in myService can't be applied to expected Parameters:, Actual Arguments:
2. Question :
In the above get method I am calling other method which calls other service method to get data from DB
List<Product> lstProduct = productComponent.readProduct(params3,params4);
which calls
Product product = productReader.readProduct(params3, params4, Product.class);
where in ProductReader.java Service class it gets data from DB by running query. I am trying to test the
List lstProduct = productComponent.readProduct(params3,params4);
in get() method so I tried mocking the Service Object but getting NullPointer Exception when I run the test.
Ad 1. Question
#RequestParam is an annotation from Spring Framework. It's used to define parameters for Controllers. The annotation is used by Spring to map the web request params to arguments which your controller accepts. Testing this behaviour would be actually testing Spring itself. I wouldn't do that. Another thing is, are you really testing a Service, or rather a Controller?
Besides, Java doesn't have the possibility to invoke a method with different arguments than defined, the only possibility is to use varargs.
Ad. Question 2
You didn't specify form where you are getting the NPE. But a first guess would be that you didn't configure Mockito correctly. For example take a look at: NullPointerException in mockito unit test

Why doesn't Mockito's when() get triggered?

I need to test a service class, but when I try to mock the dao class, it doesn't get triggered, thus not able to use ThenReturn().
I think that the problem is because I use an interface for my Dao and #Autowired in the service class (Spring MVC 3.1):
The interface:
public interface TestDao {
int createObject(Test test) throws NamingException;
}
The implementation:
#Repository
public class TestDaoImpl implements TestDao {
#Override
public int createObject(Test test) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new InsertNewTest(test), keyHolder);
return ((java.math.BigDecimal)keyHolder.getKey()).intValue();
}
}
The service:
public class RegTest {
#Autowired
TestDao testDao;
public int regTest(int .....) {
.
.
int cabotageId = testDao.createObject(test);
}
}
In the test I have:
#RunWith(MockitoJUnitRunner.class)
public class TestRegService {
#InjectMocks
private RegTest regTest = new RegTest();
#Mock
TestDao testDao;
#Test()
public void test() {
.
when(testDao.createObject(null)).thenReturn(100);
.
}
testDao.createObject(null) returns 0 (due to being mock'ed) and not 100 as I is trying to achieve.
Can anybody help, please?
Problem solved!
It was the passing test-object to createObject() that did not match. Using
testDao.createObject(any(Test.class))
did the trick!
If your test is actually passing a value to createObject, then when(testDao.createObject(null)... never gets matched. Rather than matching on null, you could match any instance of Test with testDao.createObject(any(Test.class))...
Also when you tried later to supply new Test() as the argument to match, it will literally try to match on that exact instance of Test, but presumably your real code is new-ing up a different one. So the use of Matchers.any(Test.class) as the parameter to match is the way to go.
Mockito injection mechanism don't know about Spring #Autowired or CDI #Inject annotations. It just tries to find the best candidate given the type and the name of the mock, and it can lookup private fields too. See the javadoc of #InjectMocks : http://docs.mockito.googlecode.com/hg/1.9.0/org/mockito/InjectMocks.html
The semantic you are using is correct, though if you are experiencing issues, I would rather look for incorrect interactions or incorrect arguments.
Are you sure the test variable in regTest.regTest(int...) is really null when passed to testDao.createObject(test) ?
I don't know if this is a typo in the example, but you have RegTest.regTest() calling createTest() rather than createObject(). Otherwise, I don't think #Autowired has anything to do with it, since your test itself is not running in a container with Spring management. If it is not a typo, and createTest is in fact a real and different method from createObject, then the default behaviour of a mocked object in Mockito is to return the appropriately-typed zero for numeric return types.
I think that you're right about the autowire not getting called. You could inject the dao yourself using the setTestDao() call instead. Mockito also supports spy which allows you to trace the objects code and just replace functions instead.

Resources