I have functions like
class Chainable {
public Chainable doStuff(String test) {
return doSomething(test, true);
}
public Chainable doStuff(String test, String test2) {
String toUse = test + test2;
return doSomething(toUse, false);
}
private Chainable doSomething(String test, boolean version) {
// do something
if (somethingBadHappened) {
throw SpecialException.generate();
}
return this;
}
}
SpecialException is an exception the user is supposed to see. The message of the exception purposely contains the method that threw this exception. The user would call doSomething("x") and if it fails it would show "Method 'doSomething' failed with the parameters: 'test = x | version = true'".
But the user doesn't care about the method doSomething(String, boolean) and its parameters. He used doStuff(String) and wants to see the message for that function.
So what I do is:
public Chainable doStuff(String test) {
try {
return doSomething(test, true);
} catch (SpecialException e) {
throw SpecialException.generate(e);
}
}
which sets e as the cause of the new exception and correctly shows "Method 'doStuff' failed with the parameters: 'test = x'" (the user doesn't see the stacktrace, but if I need to debug I can see what exactly happened).
Now, it works, but I have to repeat myself every time I write a new function that delegates its work to helper functions. The problem is, I don't know how I should use a helper function for this, since the SpecialException finds the method name depending on where it is generated...
Is there another, better way to do this?
Here's what you should do: show the stack trace to the user. You can then use
throw new SpecialException();
without any concerns about what method will appear.
As far as I can see, and as far as I know, this might be a nice situation to handle using aspect-oriented programming or AOP. In Java you can use AspectJ for that.
You would start by defining a "pointcut" - a specific moment in the execution of your code, for example a method invocation. Next, you would write an "advice", something that needs to be done when the pointcut is hit. You put those two together in an "aspect" and have them weaven into your bytecode during build.
In this case, you would need a pointcut that intercepts call to public methods on your Chainable, but the call should not be done from within Chainable:
pointcut publicChainableMethod() : target(Chainable)
&& call(public * *(..))
pointcut firstPublicChainableMethod() : target(Chainable)
&& call(* *(..))
&& !cflowbelow(publicChainableMethod());
The first pointcut defines any call to a public method on Chainable, the second pointcut defines a call to a method within Chainable, except it should not be called while being in the control flow of the first pointcut.
Next to that, you would need an advice that generates the new SpecialException for you:
after() throwing (SpecialException e): firstPublicChainableMethod() {
throw SpecialException.generate(e);
}
Disclaimer: I'm no AOP or AspectJ expert, so this approach might not work out-of-the-box.
Related
I have this Method that throws an IllegalArgumentException when somebody tries to call it with value 0.
I want to write several stub and mock tests - for example - for the method getFrequentRenterPoints.
I coudn't figure out any "when" or "verify" statements which are used in mocks so I mixed parts of mocks and parts of stubs together and came up with this:
#Test
public void methodGetFrequentRenterPointsShouldThrowIllegalArgumentException() {
//given
Movie movieMock = mock(Movie.class);
//when
movieMock.getFrequentRenterPoints(0);
//then
assertThrows(IllegalArgumentException.class, () -> {
movieMock.getFrequentRenterPoints(0);
});
}
Is it okay to have in a class with other Mocks, or if I want to use assertThrows should I change this into a stub? Or can I use assertThrows with mocks?
The answer from Benjamin Eckardt is correct.
But I try to approach this question from another point of view: when to use mocking? This is one of my favourite answers to that question.
So in practise:
Say your code is like (just guessing all the business objects & names...):
List<RenterPoints> getFrequentRenterPoints(int renterId) {
if(p <= 0) {
throw new IllegalArgumentException();
}
// this is just the rest of code in which your test does not enter because
// of thrown exception
return somethingToReturn();
}
For this you do not need and you should not want to mock anything here.
But when things get more complicated like your method would be like:
List<RenterPoints> getFrequentRenterPoints(int renterId) {
if(p <= 0) {
throw new IllegalArgumentException();
}
// What is this?
// It is injected in the Movie - say - like
//
// #Resource
// private RenterPointService renterPointService;
List<RenterPoints> unfiltered = renterPointService.getRenterPoints(renterId);
return filterToFrequent(unfiltered);
}
Now if you test renterId >= 1 what about this renterPointService how do you instantiate it to not get NPE? Say if it is injected and requires to pull up heavy framework for testing or it requires very heavy construction or so? You do not, you mock it.
You are testing the class Movie not the class RenterPointService so you should not bother to think how RenterPointService works but what it returns when used in the class Movie. Still: you do not mock the class Movie which you are testing.
Assuming using you are using Mockito and using annotations the mocking would be then done in your test class like:
#Mock
private RenterPointService renterPointService;
#InjectMocks
private Movie movie;
Then you would do mocking of methods for renterPointService like:
when(renterPointService.getRenterPoints(anyInt))
.thenReturn(someListContaineingMockRenterPointsForThisTest);
Usually you expect the tested production method to throw and not the mock or stub. I drafted it by using new Movie().
Furthermore in that case it does not really make sense to separate the calls into when and then because if movieMock.getFrequentRenterPoints(0); throws, assertThrows(...) will never be executed.
To apply the given/when/then structure with the assertThrows API you could extract the passed lambda in some way, but I personally don't see much benefit in it.
#Test
public void methodGetFrequentRenterPointsShouldThrowIllegalArgumentException() {
// given
Movie movieMock = new Movie();
// when/then
assertThrows(IllegalArgumentException.class, () -> {
movieMock.getFrequentRenterPoints(0);
});
}
I have a utility method used in hundreds of tests to mock the return value from a customised randomiser. Here's a (highly artificial) model of my code:
interface CardRandomiser{
Card getCard(Suit suit);
}
void mockCard(Suit suit, Face face) {
CardRandomiser rand = mock(CardRandomiser.class);
when(rand.getCard(suit)).thenReturn(new Card(suit, face));
Game.setCardRandomiser(rand);
}
This can then be used as:
mockCard(Suit.CLUBS, Face.QUEEN);
Card card = pickACardAnyCard();
assertThat(card.getFace(), is(Face.QUEEN));
However this makes some bugs a bit hard to pick up. If the method under test incorrectly asks for Suit.HEARTS then the mock returns null and the assertion correctly fails. But it's impossible to tell through the error message what was passed to the mock.
Clearly I could handle this with a verify. I could pass the mock back out of mockCard function and then separately verify that is was called with the correct value. But that really clutters up the tests assertions that are not really related to what's being tested. Given every time this method is called I am specifying an expected argument value I'd prefer to put the assertion in one place. Note that this all occurs before the method under test is called.
Ideally I'd like the when statement to throw an exception if it's called with an unexpected value. Something like:
when(rand.getCard(suit)).thenReturn(new Card(suit, face));
when(rand.getCard(intThat(not(is(suit))))).thenThrow(new IllegalArgumentException());
This works and stops the test when getCard is called which is better. But it still doesn't allow me to show what the incorrect argument was.
I also tried it using an ArgumentCaptor and then checking the captured value. But it's clear they are for verify statements rather than when statements.
Is there a standard Mockito way of doing this, or do I need to clutter my tests with verify statements?
You can configure mockito answer using thenAnswer, e.g.
private CardRandomiser mockCard(final Suit suit, final Face face) {
CardRandomiser rand = mock(CardRandomiser.class);
when(rand.getCard(any(Suit.class))).thenAnswer(new Answer<Card>() {
#Override
public Card answer(InvocationOnMock invocation) throws Throwable {
if(!suit.equals(invocation.getArguments()[0])) {
throw new IllegalArgumentException(
String.format("Value %s passed, but mocked for %s", invocation.getArguments()[0], suit));
}
return new Card(suit, face);
}
});
return rand;
}
Let's imagine, that we have a process, which accepts data of the following type:
{"date":"2014-05-05", "url":"http://some.website.com","counter":3}
This data should be validated formally: value of date should be a
parseable date, url should also conform the normal url syntax.
Also, this data should be validated logically: date should be in the future, url should be an accessible
address, returning 200 OK.
To make it clean, one must separate those two validation routines into different units (classes, utils, whatever). The desired final behaviour, however, must give user clear understanding of ALL violations, that are present in data. Something like:
{"Errors":[
"Specified date is not in the future",//Formal validation failed
"Specified URL has invalid syntax"//Logical validation failed
]}
I have seen some implementations of the required behaviour, but they
use those make use of Error objects and are full of checks like
Error.hasErrors() or error==null, which does not look elegant.
I have also seen the implementation of javax.validation, which gives you all violations on all field at once. Same approach could be implemented for content validation, but I am not sure, that this is the best way to do this.
Question: what is the best practice for handling multiple exceptions/violations of various nature?
UPD: short digest of answers: collect Violations, build an Exception, containing their context, cause and description, use an interceptor to render. See reference links from answers:
http://beanvalidation.org/1.0/spec/ JSR 303 specification
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html Spring Bean Validation
http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html Java EE validation
Which Design Pattern To Use For Validation
Why not use exceptions as regular flow of control?
You can do the following:
define an abstract Check class, as follows:
public abstract class Check {
private final List<Check> subChecks = new ArrayList<Check>();
public Check add(Check subCheck) { subChecks.add(subCheck); return this }
public void run(Data dataToInspect, List<Error> errors) {
Error e = check(dataToInspect);
if (e != null) {
errors.add(e);
return;
}
for (Check subCheck : subChecks) {
subCheck.run(dataToInspect, errors);
}
}
// Returns null if dataToInspect is OK.
public abstract Error check(Data dataToInspect);
}
class Data is the class holding the data (that needs to be checked). Can be a String, a JSON object, what have you.
class Error represents a problem detected in the data should be roughly something like:
public class Error {
private String problem;
public Error(String problem) { this.problem = problem }
public String getProblem() { return problem }
// maybe additional fields and method to better describe the detected problem...
}
You then have code that runs the check against piece of data:
public class Checker {
private final List<Error> errors = new ArrayList<Error>();
private final List<Check> checks = new ArrayList<Check>();
public Checker() {
checks.add(new DateIsParsableCheck().add(new DateIsInTheFurutreCheck());
checks.add(new UrlIsWellFormed().add(new UrlIsAccessible());
checks.add();
..
}
public void check(Data d) {
for (Check c : checks) {
Error e = c.run(d, errors);
if (e != null)
errors.add(e);
}
}
}
Slightly changed my original answer. In the current answer there is the notion of subchecks: if a check called x has a subcheck called y then the y check will run only if the x check succeeded. For instance, if the Date is not parseable there is no point to check it it is in the future.
In your case I think that all/most logical check should be sub-checks of a formal check.
I don't think there is a best practice, because it depends on what you try to achieve. In my opinion, exceptions and their messages should not be used to be displayed directly to the user. Exceptions are way too technical and do depend heavily on the context where they get thrown.
Hence, my approach would be to design a container type which collects all the exceptions thrown by your validations. Those exceptions should preserve as much of the context as possible (not in form of an exception message, but in form of fields passed into the constructor). Provide getter methods to make those fields (properties) accessible. When rendering the view, you may iterate over all entries of your container and generate a proper, human readable, i18n message.
Here is some pseudo-code as requested by the comment of #AlexandreSantos. It is not polished nor proven, just my first draft. So do not expect excellent design. It's just an example how it could be implemented / designed:
public static void main(String[] args) {
Violations violations = new Violations();
Integer age = AgeValidator.parse("0042", "age", violations);
URL url = UrlValidator.parse("http://some.website.com", "url", violations);
}
// Validator defining all the rules for a valid age value
public class AgeValidator {
// Collection of validation rules for age values
private static final Collection<Validator<String>> VALIDATORS = ...;
// Pass in the value to validate, the name of the field
// defining the value and the container to collect all
// violations (could be a Map<String, ValidationException>)
//
// a return value of null indicates at least one rule violation
public static Integer parse(String value, String name, Violations violations) {
try {
for (Validator<String> validator : VALIDATORS) validator.validate(value);
} catch (ValidationException e) {
violations.add(name, e);
}
return violations.existFor(name) ? null : Integer.parseInt(value);
}
}
I have answered this previously Here
The answer marked as good is an example of the Composite pattern being applied to validation (almost)
There are, of course, tons of frameworks for this. Something clever you could do, that I have used to great effect, is to use an aspect + a validator or make sure whole swaths of new and existing code get checked auto-magically.
#Aspect
public class DtoValidator {
private Validator validator;
public DtoValidator() {
}
public DtoValidator(Validator validator) {
this.validator = validator;
}
public void doValidation(JoinPoint jp){
for( Object arg : jp.getArgs() ){
if (arg != null) {
Set<ConstraintViolation<Object>> violations = validator.validate(arg);
if( violations.size() > 0 ){
throw buildError(violations);
}
}
}
}
private static BadRequestException buildError( Set<ConstraintViolation<Object>> violations ){
Map<String, String> errorMap = new HashMap<String, String>();
for( ConstraintViolation error : violations ){
errorMap.put(error.getPropertyPath().toString(), error.getMessage());
}
return new BadRequestException(errorMap);
}
}
Here is a snip of bean config
<aop:config proxy-target-class="true">
<aop:aspect id="dtoValidator" ref="dtoValidator" order="10">
<aop:before method="doValidation"
pointcut="execution(public * com.mycompany.ws.controllers.bs.*.*(..))"/>
</aop:aspect>
</aop:config>
Now all of your controller methods will have that validation code applied here and into the future.
Designing it using exceptions will work, but you will have to write a whole framework to deal with exceptions, many of which can't be handled by your exception interceptor. If you feel the coding itch, then go for it. My advice would be to have different classes of exceptions. Some of them would be critical exceptions, some would be just warnings... you got the picture.
You could (I hope you do) use a proven framework that can handle that beautifully. I speak of JSR 303 and Bean Validation through Spring: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html
It takes a while to get used to, but it will pay you back 1000 fold.
I would simply pass around a list of all the errors. The items in the list may not be just exceptions, but rather some objects wrapping more information about the errors, such as name of wrong parameter, its wrong value, position of the error in the string, type of validation (formal, ligical), ID of the error message for localized display to user... Each method on the processing path may append to the list.
I'm currently working in a project in Liferay in which i'd like to be able to access my method and parameters these methods were given, in the history. This is done in case there is an exception being thrown in certain blocks of code.
I've already searched and it is easy to get the method name history (Thread.currentThread().getStackTrace();) but i'd like to also know what parameters were given to these methods.
For example:
public class A {
public static void main(String[] Args) {
try {
System.out.println(new B().someMethod(5));
} catch (Exception e) {
//GET HISTORY
}
}
}
public class B {
public int someMethod(int i) throws Exception {
i += 2;
throw new Exception("Expected Exception to Generate History Search");
return i;
}
}
Is it possible to learn how can i, in class A, when I catch the exception, all that data? And of so, how do I do that?
You can use Aspect Oriented Programming. Look at AspectJ for example.
The following aspect will trace all public method calls during your programs execution.
This can be fine-tuned to work with your own requirements. The pointcut can for example be adjusted to only take your own packages. The print statements can be changed into using some logging framework.
public aspect Trace {
pointcut publicMethodExecuted(): execution(public * *(..));
after(): publicMethodExecuted() {
System.out.printf("Enters on method: %s. \n", thisJoinPoint.getSignature());
Object[] arguments = thisJoinPoint.getArgs();
for (int i =0; i < arguments.length; i++){
Object argument = arguments[i];
if (argument != null){
System.out.printf("With argument of type %s and value %s. \n", argument.getClass().toString(), argument);
}
}
System.out.printf("Exits method: %s. \n", thisJoinPoint.getSignature());
}
}
You should consider using logging in your application.
You should definitely look in to logging in your application. If you want to avoid cluttering your code too much (I personally hate the constant log.debug(...) statements at start and end of each method), consider using Aspect Oriented Programming (google it for a whole host of good guides on it, or there's a decent aop guide using Spring here, just scroll down to the LoggingAspect), which will allow you to simply annotate methods or entire classes that you want logged.
I am implementing an interface which defines a method that can throw an exception if the parameters are not valid. What constitutes valid parameters depends on the implementing class. The interface also defines an isValid() method which can be used to check the parameters but returns a boolean rather than throwing an exception. I have found that implementing both methods will cause a lot of duplication. Consider this made up example:
public class Something implements SomeInterface {
// Other class stuff
public void doTheThing(SomeParameter sp) throws SpecificRuntimeException {
if(sp == null) throw new ParameterCannotBeNullException();
if(sp.getNonZeroInt() == 0) throw new ShouldBeNonZeroException();
if(!sp.someOtherCondition()) throw new SomeConditionNotMetException();
...
}
public boolean isValid(SomeParameter sp) {
if(sp == null) return false;
if(sp.getNonZeroInt() == 0) return false;
if(!sp.someOtherCondition()) return false;
...
return true;
}
}
The problem is the checks in both methods must be consistent, and are essentially duplicated logic. I've been trying to consolidate the checks so that both methods use the same checks but the behaviour is still retained. Some things I considered:
in doTheThing() have the line if(!isValid(sp) throw new RuntimeException();
separate the exception throwing part into a separate, private method, say checkParameter() and in isValid() do: try { checkParameter(sp); return true; } catch (SpecificRunTimeException e) { return false; }
The problem with 1. is that the specific exception is lost, and I want to provide as detailed an exception as possible. The problem with 2. is using the exception mechanism seems... wrong somehow. This part of the code may be performance sensitive, and I don't want to depend on something that's fundamentally slower than it needs to be (if I have to do it this way and profiling doesn't show a problem, fair enough... but what if is a problem?). Or has the performance hit of using exceptions this way been shown to be negligible?
What is the best way to refactor this code to use the same validity checking logic?
What if your create a isValidParam method that returns a bean like:
class ValidBean {
private boolean isValid;
private Exception exceptionOnInvalid;
public ValidBean(boolean isValid, Exception exceptionOnInvalid) {...}
// accessors
}
With the method being:
private ValidBean isValidParam(SomeParameter sp) {
if (sp == null) {
return new ValidBean(false, new ParameterCannotBeNullException());
}
if (sp.getNonZeroInt() == 0) {
return new ValidBean(false, new ShouldBeNonZeroException());
}
if (!sp.someOtherCondition()) {
return new ValidBean(false, new SomeConditionNotMetException());
}
…
return new ValidBean(true, null);
}
And then you do:
public boolean isValid(SomeParameter sp) {
return isValidParam(sp).isValid();
}
And
public void doTheThing(SomeParameter sp) throws SpecificRuntimeException {
ValidBean validbean = isValidParam(sp);
if (! validBean.isValid()) {
throw validBean.getExceptionOnInvalid();
}
...
}
I don't know if it's the best way, but a way is to have an internal method like this:
private boolean isValidInternal(SomeParameter sp, boolean throwIfInvalid)
throws SpecificRuntimeException
Then you call isValidInternal with true from the doTheThing method, and false from the public isValid method.
Edit: And then to implement isValidInternal, you have the logic for testing validity once, but either return false or throw an exception as per the throwIfInvalid flag.
This can be a murky issue; when it comes to exceptions in APIs I've never found a really clear, logical, satisfactory answer to every case.
Do you expect every user of isValid() to be using it to guard a subsequent call to doTheThing()? If so, the client code would be clearer to use the standard try/catch idiom instead, and you may not need an isValid() method at all.
(You'd still have to ponder whether the exception should be checked or unchecked; the line can be a fine one and I won't go into it here.)
And if you don't see isValid() being used this way, then just implement it with a try/catch of your own; I know it feels dirty, but it's better than the alternatives!
Your urge to "say it once and only once" is laudable. Good thinking; it'll be worth the effort.
Maybe you can create an abstract class that implements the interface and provides the default implementation for isValid().
If your object is mutable and has setters, perhaps you could move the check that throws IllegalArgumentException into each one and then call them. You'll have a more fine-grained view of what went wrong that way.
The fact that your code checks the arguments for sanity and returns runtime exceptions is a strong indication that you want to report programming error, i.e. your API is used/called in a way it should not be used/called. Since you could expect that your API is called with valid arguments, I wouldn't expect that your second solution to be problematic.
P.S.: You should not use runtime exception types in a method's throws declaration. But you should state those runtime exceptions in the method's Javadoc #throws documentation.