My method looks like this
public EP updateEP(long id, EP eP) {
EE eE = eRepo.findById(id).orElseThrow(EntityNotFoundException::new);
//some code
}
and my test method looks like this
#Test
public void testUpdateEWhenEExists() {
long id = 1l;
EE eE = new EE();
eE.setPosId(1l);
eE.setPosName("pos");
EPE ePE = new EPE();
ePE.setEId(id);
when(eRepo.findById(id).orElseThrow(EntityNotFoundException::new)).thenReturn(eE);
//some code
}
And it always throw EntityNotFoundException.I want to be returned to me eE instead of EntityNotFoundException
EDIT
#Test
public void testUpdateEPWhenEExists() {
long id = 1l;
EE eE = new E();
eE.setPositionId(1l);
eE.setPosName("pos");
EPE ePE = new EPE();
ePE.setEId(id);
when(eRepo.findById(id)).thenReturn(Optional.of(eE));
}
In this case error is
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
EPE cannot be returned by findById()
findById() should return Optional
From the code sample you've provided it seems that eRepo.findById(id) returns an Optional.
eRepo.findById(id).orElseThrow(...)
receives that Optional and basically checks, if the Optional is empty. If not, it returns the instance of EE, otherwise it throws the specified exception.
In your test there is no need to call
orElseThrow(EntityNotFoundException::new)
because you're explicitly mocking the behaviour of findById.
Just do it like that:
when(eRepo.findById(id)).thenReturn(Optional.of(eE));
I am posting this to help anyone find this quicker. I needed to assert the message and condition for the exception in a .orElseThrow() from an JPA repository. The normal case is obvious to return Optional.of(someDataYouAlreadyMockedUp), but to get the exception , the repository stream must get a null (Empty) so use Optional.empty() ...
In my code I have
License license = licenseRepository.findById(licenseId).orElseThrow(() ->
new BadRequest("License " + licenseId + " not found."));
To test and assert the value in the Test I mock it like this:
when(licenseRepository.findById(1L)).thenReturn(Optional.empty());
And then call and assert like this:
try {
SomeDto result = someService.getSomeStuffByLicenseId(1L);
fail("should have already thrown exception here!");
}catch (BadRequest br) {
assertEquals("License 1 not found", br.getMessage());
}
Related
Trying to write a test that will call my method, when that method makes a call to another method we will throw a custom exception i have made. Here i have simplified it all
2 functions
public MyJsonResponse hello() {
MyJsonResponse response = new MyJsonResponse();
response.setErrorMessage("1");
response.setStatus("some status");
response.setData("1");
response.setHttpResponse(200);
try{
hi();
return response;
}catch (MyServiceException e) {
response.setErrorMessage(e.getMessage());
response.setStatus("error creating");
response.setData("2");
response.setHttpResponse(e.getResponseStatus());
return response;
}
}
public String hi() throws MyServiceException{
LOG.error("Exception");
return "yea";
}
The test I have written is this
#Test
public void myTest() throws Exception {
given(service.hi()).willAnswer( invocation -> { throw new MyServiceException("abc msg",511); });
MyJsonResponse actual = service.hello();
Assert.assertNotNull(actual);
assertEquals(511, actual.getHttpResponse());
}
But unfortunately the result is as follows
java.lang.AssertionError:
Expected :511
Actual :200
Please, be sure that you are using a spy as you want to use the actual code for some methods of your mocked service and just stubbing specific methods of it. Please, see for instance this related SO question about the subject.
Also, consider modifying your test definition to use willThrow instead of willAnswer: as pointed out by #eis, you can still use the later, but the former is more straightforward.
Your code will look similar to this:
#Test
public void myTest() throws Exception {
MyService service = spy(MyService.class);
willThrow(new MyServiceException("abc msg",511))
.given(service)
.hi()
;
// As pointed out by #eis, you can still use willAnswer
// willAnswer(
// invocation -> { throw new MyServiceException("abc msg",511);}
// )
// .given(service)
// .hi()
// ;
MyJsonResponse actual = service.hello();
Assert.assertNotNull(actual);
assertEquals(511, actual.getHttpResponse());
}
regarding what you explain and what your code look like, I am not sure if I have well understood.
Thus, if you want that, your hi() : function throws an exception.
You have to make it first throws an exception. Take a look at code below!
public String hi() throws MyServiceException{
/*LOG.error("Exception");//No don't just log, throw a real exception as below*/
throw new MyServiceException("text here, if your constructor support it or nothing otherwise")
/*return "yea";//Nothing to return? we have just break the code by throwing the exception above*/
}
After that, please be very sure that your 'MyServiceException.getHttpResponse()' will really return 511
For this test to make sense, your hi() call should be done calling another service that you stub/mock in your test class. You're not doing that, so this approach won't work.
You wrote "the real method that hi represents does a lot", so it's about time you extract that to another service.
I have a controller end point that looks something like so
#POST
public JobComponentGetResponse createJobComponent(
#PathParam("jobId") Integer jobId,
#Valid JobComponentPostRequest request
) {
JobComponentRecord newJobComponent = dao.jobComponent.newRecord();
newJobComponent.setJobId(jobId);
newJobComponent.setLabel(request.label);
newJobComponent.setSqft(request.sqFt);
newJobComponent.insert();
return new JobComponentGetResponse(newJobComponent);
}
And a corresponding unit test
#Test
public void createJobComponent_createsAndReturnsTheDesiredRecord() {
JobComponentPostRequest request = new JobComponentPostRequest();
JobComponentRecord jobComponent = spy(new JobComponentRecord());
when(dao.jobComponent.newRecord()).thenReturn(jobComponent);
when(jobComponent.insert()).thenReturn(null);
JobComponentGetResponse response = jobComponentController.createJobComponent(jobId, request);
assertThat(response, samePropertyValuesAs(request));
}
I'm trying to test the response of my controller but I keep getting a null pointer exception when the controller calls newJobComponent.insert()
I've tried doing when(jobComponent.insert()).thenReturn(null); and that doesn't work either.
I suspect that your dao.jobComponent.newRecord() returns null even if you do : when(dao.jobComponent.newRecord()).thenReturn(jobComponent);
What is dao.jobComponent exactly and where does it comes from ?
EDIT : I don't have a full overview of your code but a getter for JobComponentRecord would be a good idea and you could easily determine his return value with mockito.
I have actual method below:
public ResponseEntity<Message> catEnter(#PathVariable("catId") BigInteger catId, #RequestBody Catrequest catReq, HttpServletRequest request) throws CatDataException, InvalidCatExcecatption {
Message message = new Message();
try {
message = catManager.submitData(catReq.getMessage(), catId, request);
} catch (IOException e) {
throw new CatDataAppException(e.getMessage());
}
return (ResponseEntity<Message>) restResponse(message, request.getMethod());
// Getting null pointer exception in above line
}
I am using mockito for my test code as below:
#Test
public void submitData() throws Exception {
Message mes = new Message();
mes.setCode("00");
mes.setMessage("hi");
ResponseEntity<Message> responseentity = ((ResponseEntity<Message>) catController.catEnter(BigInteger.valueOf(3431), catRequest, mockRequest));
}
I'm getting null pointer exception, Message going as a null, even I set the value explicitly?
Here:
You pass mockRequest when making that call to your production code:
ResponseEntity<Message> responseentity = ... catController.catEnter(... mockRequest));
And your production call does:
return (ResponseEntity<Message>) restResponse(message, request.getMethod());
So the only conclussion: mockRequest is null!
So, first make sure that the passed variable is not null; like:
Request mockedRequest = mock(Request.class);
Or, use the #Mock annotation in case that mockedRequest is a field in your test class.
On top of that; you probably want to do some mock-specification, like:
when(mockedRequest.getMethod()).thenReturn( whatever )
But beyond that, you are lacking a lot of the fundamental basics of Java:
naming conventions: variable names go camelCase, like entityResponse. And typically, tests are named like testCatEnter to express the method that is tested.
You have casts ... where they are not required.
You have quite some code there ... that is unused, like the mes declaration in your test method.
Long story short: I have the feeling that you are overburdening yourself dramatically. First learn the basics; then go for the advanced Mockito stuff.
I have a Service and a Controller .
Each method in the service its preconditions , for example :
public void doSomething(Parameter para1 , Parameter para2 ...) {
if ( something wrong ) {
throw new RuntimeException1();
}
if ( another thing wrong ) {
throw new RuntimeException2();
}
// continue do something
}
And in the Controller layer , there are two methods , one is showForm() which displays form for user to input ; another is doApplyForm() which accepts form and calls the underlaying Service.doSomething().
The following is the pseudo code (I eliminated some BindingResult , attr.addFlashAttribute codes ) :
#Injected Service service;
public String showForm() {
if ( something wrong ) {
throw new RuntimeException1();
}
if ( another thing wrong ) {
throw new RuntimeException2();
}
return "showForm";
}
public String doApplyForm(#Validated Form form) {
try {
service.doSomething(para1 , para2 ...);
return "redirect:/";
} catch (Exception e) {
// error handling
return "redirect:/error";
}
}
It works well , but I am not satisfied. There're bad smells within.
The problem is in the showForm() , which shares identical preconditions with Controller.doSomething() .
If Service.doSomething() add another preconditions in the future , Controller.showForm() has to do correspondent changes.
I wonder if there're any design pattern or frameworks to eliminate such bad smell ?
Java8's functional solutions are welcome.
Thanks.
You can define a util class called Preconditions and move all your validation logic there. It's a common pattern and there are a number of frameworks that make use of it. For example, Guava: Preconditions docs.
At least like this your if (condition) throw new exception will be capsulated and easier to manage.
Introduce a parameter object for the service request and put the validation logic into the request object. E.g.
public class DoSomethingRequest {
private Parameter param1;
private Parameter param2;
public void validate(){
if ( something wrong ) {
throw new RuntimeException1();
}
if ( another thing wrong ) {
throw new RuntimeException2();
}
}
}
Your service will be more easy
public void doSomething(DoSomethingRequest request) {
request.validate();
}
so the controller
public String showForm() {
DoSomethingRequest request = ... // obtained somehow
request.validate();
// ...
return "showForm";
}
This encapsulates the service method's preconditions in an object.
I am new in writing the junit test cases and need help. I read about possible solutions but they are not working at this point.
Main class looks like below, which calls the method of ther class addResponseData(This method only sets values in session and returns nothing). Please see the code as per below.
#Test
public void testPublishData_Success() throws java.lang.Exception {
when(GetPropValues.getPropValue(PublisherConstants.ATMID)).thenReturn("ATM");
when(GetPropValues.getPropValue(PublisherConstants.DATA_SOURCE)).thenReturn("PCE");
ReadAndWriteFiles mockFiles = Mockito.mock(ReadAndWriteFiles.class);
PowerMockito.whenNew(ReadAndWriteFiles.class).withNoArguments().thenReturn(mockFiles);
Mockito.when(mockFiles.getAllFiles()).thenReturn(null);
KafkaProducer mockProducer = Mockito.mock(KafkaProducer.class);
PowerMockito.whenNew(ReadAndWriteFiles.class).withAnyArguments().thenReturn(mockProducer);
producer.publishData(null, "Test", "Data1");
}
ResponseWrapper signerResponse;
try {
privateClassObj.ensureDataLoaded(objSession); // Loads the required data into objSession)
signerResponse = new ResponseWrapper(ResponseType.SUCCESS);
signerResponse.addResponseData("signerList", objSession.getSignerList());
signerResponse.addResponseData("additionalSignerList", objSession.getAdditionalSignerList());
}
catch (ServiceException err) {
signerResponse = new ResponseWrapper(ResponseType.PARTIAL_SUCCESS);
}
return signerResponse;
}
TestClass: I have written junit test case as per below.
#Test
public void testSuccessfulCallWithSigners() {
List<Signer> signerList = setSignerList();
List<Signer> additionalSignerList = setSignerList();
when(objSession.getSignerList()).thenReturn(signerList);
when(nsbSession.getAdditionalSignerList()).thenReturn(additionalSignerList);
ResponseWrapper output = signerController.getUsers(request); // actual method call
assertEquals(output, responseWrapper);
}
This test case is failing because, I always get empty signerList and additionalSignerList.(test case result is getAdditionalSignerList() method should return List) Please let me know what am I doing wrong here. Thanks in Advance. I am also posting my the code of setSignerList() in case if you want to see it for reference.
private List<Signer> setSignerList() {
List<Signer> signerList = new ArrayList<Signer>();
signerList.add(primarySigner); // primarySigner is mock object.
return signerList;
}
You have mocked objSession and also you have returned your empty list when these two methods get called by the test case.
when(....).thenReturn(....) is used to specify a condition and a return value (Stubbing) for this condition.As you have mocked it and return your desired list using stubbing, it will not return the list returned by actual call.
List<Signer> signerList = setSignerList(); // EMPTY LIST
List<Signer> additionalSignerList = setSignerList(); // EMPTY LIST
when(objSession.getSignerList()).thenReturn(signerList); //MOCK
when(nsbSession.getAdditionalSignerList()).thenReturn(additionalSignerList); // MOCK