Hi All I am doing Junit testing on Spring MVC project. Here the following code
Method to be tested
public UserDetails getUserInfo(String userID) {
Session session = sessionFactory.getCurrentSession();
UserDetails userDetails = new UserDetails();
Query query = null;
try {
query = session.createQuery("From UserDetails where user_Id=:userID").setParameter("userID", userID);
List < UserDetails > list = query.list();
if (CollectionUtils.isNotEmpty(list)) {
userDetails = list.get(0);
} else {
throw new RuntimeException("No identifier found on our records! for '" + userID + "'");
}
} catch (Exception e) {
throw e;
}
return userDetails; }
I am testing it for both positive and negative cases.
Here is my negative testcase
#Autowired
DaoLayer layer;
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
#Transactional
public void getUserInfoNegative() throws Exception
{
String[] inputs={"W12348","ABCDEF","123456"};
for(int i=0;i<inputs.length;i++)
{
System.out.println("/****** Invoking getUserInfo with Input "+inputs[i]+" *********/");
String msg="No identifier found on our records! for '"+inputs[i]+"'";
thrown.expect(RuntimeException.class);
thrown.expectMessage(msg);
layer.getUserInfo(input);
}
}
Here I am trying to input wrong userID's and expecting runtime exception to be thrown. The code works fine it throws the expection along with the message. But the issue is it is invoking only one time for the first input, other input values are not executed. How Can I make it to work in loop??
Note: Junit testcase passed and shows green bar.
I have altered the code but that too doesnot work for loop. Where I am doing wrong??
#Test
#Transactional
public void getUserInfoNegative() throws Exception
{
String[] inputs={"W12348","ABCDEF","123456"};
for(int i=0;i<inputs.length;i++)
{
System.out.println("/****** Invoking getUserInfo with Input "+inputs[i]+" *********/");
String msg="No identifier found on our records! for '"+inputs[i]+"'";
getUser(msg,inputs[i]);
}
}
public void getUser(String msg,String input)
{
thrown.expect(RuntimeException.class);
thrown.expectMessage(msg);
layer.getUserInfo(input);
}
Related
I have a webapp with a controller layer, a service layer, and a data access layer.
Checkmarx complains about improper error handling when I call getSingleResult in my data access layer where methods look like this :
public FilterWorkflow getNextStatusesForAction(final Long currentStatus, final String actionRequested) {
Query query = this.getEntityManager().createQuery(GET_NEXT_STATUSES_FOR_ACTION);
query.setParameter("currentStatus_Id", currentStatus);
query.setParameter("actionRequested", actionRequested);
return (FilterWorkflow) query.getSingleResult();
}
This is called from the service layer like this :
#Override
#Transactional(value="txManager", rollbackFor = Exception.class)
public SomeFilter executeAction(SomeFilter bf, final String action requested) throws Exception {
Long currentStatusID = bf.getFilteStatus().getTableId();
FilterWorkflow fw = this.someDAO.getNextStatusesForAction(currentStatusID, actionRequested);
return this.updateFilterStatus(fw, bf, actionRequested);
}
which gets called in the controller layer :
public String execute(SomeFilter bf, final String command) {
try {
bf = this.someService.executeAction(bf, command);
} catch (Exception e) {
LOGGER.info(e.getMessage());
FacesUtil.addErrorMessage(this.msgApp.getMessage("error_message"));
return null;
}
return null;
}
I think the exception is handled, because there is nothing more to do about the exceptions that getSingleResult can throw, other than displaying an error message to the user, and logging that error.
Am I missing something ?
I know that in Java a method can return only one return type... But if there is any possiblity to this, kindly let me know. From the below method I am trying to return a list if condition satisfies else i am trying to return an error message.
Here is my code:
#RequestMapping(value = "/getcompanies", method = RequestMethod.POST)
public List<CompanyMaster> getCompanies(#RequestBody UserDetails user) {
String OrgLoginId = user.getOrgLoginId();
String password = user.getuPassword();
String checkLoginId = null;
String uPassword = null;
String encPassword = null;
String loginId = null;
String checkAuthorized = null;
// String loginId=userService.getLoginId(OrgLoginId);
List<Object[]> CheckIdPassword = userService.checkLoginId(OrgLoginId);
List<Object[]> results = CheckIdPassword;
for (Object[] obj : results) {
checkLoginId = obj[0].toString();
if (null == obj[1]) {
uPassword = "";
} else {
uPassword = obj[1].toString();
}
loginId = obj[2].toString();
}
checkAuthorized = loginId.substring(0, 3);
if (null != password) {
MD5 md5 = new MD5();
encPassword = md5.getPassword(password);
}
if (checkLoginId == null) {
return "Incorrect loginId..Please enter valid loginId";
} else if (encPassword.equals(uPassword)) {
if (checkAuthorized.equals("STE")) {
List<CompanyMaster> companyList = userService.getCompanyList(OrgLoginId);
return companyList;
} else {
return "You are not Authorized";
}
} else {
return "Incorrect Password";
}
Yes its possible, create a custom Exception say 'MyAppException' and throw that exception with the error message you want.
Write your logic in a try{}catch block and throw the exception in catch so that the response has the error message
public List<CompanyMaster> getCompanies(#RequestBody UserDetails user) throws MyAppppException
{
try
{
//your logic which throws error
return companyList;
}
catch( final MyAppException we )
{
throw new MyAppException("User not found", HttpStatus.NOT_FOUND);
}
}
Refer this link
https://www.codejava.net/java-core/exception/how-to-create-custom-exceptions-in-java
You can achieve this by creating a new presenter Class which contains List and status of type String and change the return type of getCompanies method to presenter class like
public CompaniesPresenter getCompanies()
And your CompaniesPresenter class should look like
public class CompaniesPresenter {
private List<CompanyMaster> companyMaster;
private string status;
//default constructor
public CompaniesPresenter(){
}
//parameterized constructor to return only string in exception case
public CompaniesPresenter(Stirng status){
this.status = status;
}
//parametirized constructor to return success case
public CompaniesPresenter(List<CompanyMaster> companyMaster, Stirng status){
this.companyMaster = companyMaster;
this.status = status;
}
//getters and setters
}
This is how your updated method lokks like
#RequestMapping(value = "/getcompanies", method = RequestMethod.POST)
public CompaniesPresenter getCompanies(#RequestBody UserDetails user) {
String OrgLoginId = user.getOrgLoginId();
String password = user.getuPassword();
String checkLoginId = null;
String uPassword = null;
String encPassword = null;
String loginId = null;
String checkAuthorized = null;
// String loginId=userService.getLoginId(OrgLoginId);
List<Object[]> CheckIdPassword = userService.checkLoginId(OrgLoginId);
List<Object[]> results = CheckIdPassword;
for (Object[] obj : results) {
checkLoginId = obj[0].toString();
if (null == obj[1]) {
uPassword = "";
} else {
uPassword = obj[1].toString();
}
loginId = obj[2].toString();
}
checkAuthorized = loginId.substring(0, 3);
if (null != password) {
MD5 md5 = new MD5();
encPassword = md5.getPassword(password);
}
if (checkLoginId == null) {
return new CompaniesPresenter("Incorrect loginId..Please enter valid loginId");
} else if (encPassword.equals(uPassword)) {
if (checkAuthorized.equals("STE")) {
List<CompanyMaster> companyList = userService.getCompanyList(OrgLoginId);
return new CompaniesPresenter(companyList,"success");
} else {
return new CompaniesPresenter("You are not Authorized");
}
} else {
return new CompaniesPresenter("Incorrect Password");
}
This is not tested please make sure for any compilation errors
vavr's Either class would be a good choice.
The usage of custom exception is most reasonable solution. However, creating custom exception for just one case is not ideal always.
Another solution is to return empty List from your method, check if the List is empty in your servlet (or wherever you are invoking this method from), and show error message there.
It seems like you want to return multiple error messages for different cases. In this case, custom exception is recommended solution. If you don't like custom exceptions, you can return List<Object> and populate error message as the first element in the list. In the place where this List is obtained, check if the first element is instanceOf String or CompanyMaster. Based on what it is, you can perform your operations. This is a weird but possible solution (only if you don't like custom exceptions).
You need to understand the problem first. You are mixing two things here, first authorization, does the user has correct privileges to get company details, second giving the company details itself. Let's understand the first problem when a user tries to access "/getcompanies" endpoint will you let him in if does not have access, in REST world your security model should take care of it. I would use spring security to achieve this. My recommendation would be to explore on "interceptor" and solve the problem of invalid user. This will make your other problem easy as your "/getcompanies" endpoint can focus only on getting the details and return it (SRP).
I'm trying to delete an Object using Hibernate but the thing is not deleting.
I debugged the program to make sure the Object is correct and it is, so I'm guessing the problem might be in something I have no idea what it is ... annotations, configuration ?? Maybe someone can help !
Here's the program:
Controller:
// Erased the imports to make it simpler
#RestController
public class Controlador {
#Autowired
private FisicHostDao fisicHostDao;
#Autowired
private CredentialService credentialService;
#RequestMapping(value = "/fisicHost/{id}/credentials", method = RequestMethod.GET, produces = APPLICATION_JSON_UTF8_VALUE)
public List<Credential> credentialsByFisicHost(#PathVariable(value = "id") final Long fisicHostId, ModelMap modelMap){
FisicHost optionalFisicHost = fisicHostDao.findById(fisicHostId);
if (optionalFisicHost == null) {
// Responder con 404
}
FisicHost fisicHost = optionalFisicHost;
return fisicHost.getCredentials();
}
// This is the method handling the request / response
#RequestMapping(value = "/fisicHost/{id}/credentials", method = RequestMethod.POST)
public String deleteCredential(#PathVariable(value = "id") String credId){
String[] parts = credId.split("-");
int id = Integer.parseInt(parts[1]);
Credential c = credentialService.getCredentialById(id);
credentialService.delete(c);
return "justreturnsomething";
}
}
As you can see in the picture the object is not null and it does matches the object I want to delete ...
So why is it not deleting ?
I'm guessing you need to commit a transaction so that the delete actually gets committed to the database.
See Transaction
Eg:
Session session = sessionFactory.openSession();
try {
session.beginTransaction();
try {
doHibernateStuff(session);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
throw e;
}
} finally {
session.close();
}
I have got a problem with transaction rollback.
I need to first insert a user into the database, and then insert into another table some kind of log of who inserted the user.
If there is an exception when inserting this log-message, the whole transaction should be rolled back (i.e. user needs to be removed again).
The .ear is deployed on Wildfly 8.1, persistence is achieved through Hibernate with MySQL.
My class looks like this
#Stateless
#Remote(AdministratorBiznesowyService.class)
#Transactional(rollbackOn = Exception.class)
public class AdministratorBiznesowyServiceBean implements AdministratorBiznesowyService {
The method looks like this
#Override
#Transactional(rollbackOn = Exception.class)
public void insertUser(String userSessionId, User user) throws AdministratorBiznesowyException {
checkPermission(userSessionId);
try {
userBusiness.insertUser(user);
log.insertLog(
authenticationObjectBusiness.getUserIdForSessionId(userSessionId),
LogEnum.CREATE, user);
} catch (AuthenticationException e) {
ServerLogModule.logActionError(Messages
.getErrorMessage("server.authorization.noPermission"));
throw new AdministratorBiznesowyException();
} catch (Exception e1) {
ServerLogModule.logActionError(Messages
.getErrorMessage("server.exception"));
throw new AdministratorBiznesowyException();
}*/
}
The insertUser implementation in userBusiness:
#Override
public void insertUser(User user) throws AdministratorBiznesowyException {
try {
UserEntity userEntity = adminConvertUtils.convertUserToEntity(user);
userEntityFacade.create(userEntity);
} catch (Exception e) {
throw new AdministratorBiznesowyException();
}
}
And my log.insertLog currently for test-purposes just throws an exception.
throw new LogException();
and its implementation is like this:
#ApplicationException(rollback=true)
public class LogException extends RuntimeException {
AdministratorBiznesowyException:
#ApplicationException(rollback = true)
public class AdministratorBiznesowyException extends CommunicationException {
CommunicationException:
public class CommunicationException extends Exception {
So now, when I successfully call insertUser and directly after that get an exception, the new user still gets added to the database (I check through MySQL Workbench).
What else can I do to get this to rollback?
If any other code is needed, please comment, thank you in advance.
In runtime this code works:
// Service class
class UserService {
ApiClient api
User create(User user) throws EmailTakenException, UsernameTakenException {
User savedUser
try {
savedUser = api.users.create user
setEnabled savedUser.id, true
return savedUser
}
catch(ApiException ex) {
switch(ex.subStatus) {
case SubStatus.USERS_EMAIL_TAKEN:
throw new EmailTakenException()
break
case SubStatus.USERS_USERNAME_TAKEN:
throw new UsernameTakenException()
break
}
}
}
}
called from a controller:
// Controller class, an action
def create(CreateCommand cmd) {
if(request.get) {
render view: 'create'
return
}
if(!cmd.validate()) {
flash.model = cmd
redirect action: 'create'
return
}
def user = new User()
bindData user, params
try {
userService.create user
flash.success = 'ui.save.success'
}
catch(EmailTakenException ex) {
flash.model = cmd
flash.error = 'ui.email.taken'
}
catch(UsernameTakenException ex) {
flash.model = cmd
flash.error = 'ui.username.taken'
}
redirect action: 'create'
}
The "User", "SubStatus", and "ApiException" class comes from a jar library dependency. The ApiClient throws an ApiException when something goes wrong.
In runtime this code works perfectly, but when I write a Spec for this, it throws an UndeclaredThrowableException. Here's the Spock Specification:
ApiClient api
UsersApi apiUsers
void setup() {
api = Mock()
apiUsers = Mock()
api.users >> apiUsers
service.api = api
}
def "create: it should be able to throw an exception when email is already taken"() {
setup:
def user = new User(email: 'foo#cod.com', username: 'foo', name: 'Bar Foo')
def exception = Mock(ApiException)
exception.subStatus >> SubStatus.USERS_EMAIL_TAKEN
when:
service.create user
then:
thrown(EmailTakenException) // GrailsException is runtime
1 * apiUsers.create(_ as User) >> { throw new ApiException(400, SubStatus.USERS_EMAIL_TAKEN, null) }
}
Maybe you could rewrite your test using the #FailsWith annotation?
http://code.google.com/p/spock/wiki/SpockBasics#Extensions