I was wondering if anyone could help - I am writing a custom Json serializer, extending from JsonSerializer, and I want to wrap any exceptions that could be thrown in my own custom exception, extended from IOException. However, whenever I run any unit tests (using junit) to confirm that the exception is thrown it is failing, saying that -
Expected: (exception with message a string containing "Unable to serialize!" and an instance of com.cybersource.profile.serializer.MySerializerException)
got: <com.fasterxml.jackson.databind.JsonMappingException: Unexpected IOException (of type com.cybersource.profile.serializer.MySerializerException): Unable to serialize!>
Any idea how to get around this, or is it not possible to throw a custom exception?
Got it sorted - turns out for a custom exception you shouldn't extend from IOException, but JsonProcessingException!
Related
I'm using Spring Boot and Spring Data JPA, and i have a generic method that returns a generic type object and a custom exception that needs to be thrown from the generic method.
Unfortunately, I get an error from the IDE suggesting that I should throw the generic Throwable instead of my custom exception. Whenever I try to throw my exception, I get a compilation error.
The generic method -> Gets one of three client types from the database, or throws an ClientNotFoundException stating that the client wasn't found in db:
public static <T> T isExists(JpaRepository repository, int id, ClientType clientType) throws Throwable {
T fromDB = (T) repository.findById(id).orElseThrow(() -> new ClientNotFoundException("Error getting info from dababase", Calendar.getInstance(), null, clientType));
return fromDB;
}
What seems to be the problem? How can I throw my custom exception from my generic method? Thanks :)
edited:
If I manually throw from method header ClientNotFoundException, the lines go red and the app is not compiling-
The compilation error that I get is:
java: unreported exception java.lang.Throwable; must be caught or declared to be thrown
IDE (using IntelliJ) suggests 3 options:
Convert exception to Throwable
Annotate with #SneakyThrows
try/catch
The suggestions are not the best for me, so I'd like to check other solutions..
This question already has answers here:
Why won't this Expect Exception Junit Test Work?
(2 answers)
Closed 6 years ago.
I'm having an issue with a test case.
The method being tested has a try / catch that catches a MalformedURLException but during testing I get a failure due to a Junit AssertionError that expects a MalformedURLException. But I can't find out what it is actually throwing! Here is my code (created as a MWE in eclipse).
My method that I want to test
public void throwMalFormedURLException(){
String s = new String("www.google.com");
try{
url = new URL(s);
}catch (Exception e){
e.printStackTrace();
e.getClass();
e.getCause();
}
}
the test method
#Test (expected = MalformedURLException.class)
public void testThrowMalFormedURLException() {
MWE testClass = new MWE();
testClass.throwMalFormedURLException();
System.out.println("End of test");
}
This is the output in the console
End of test error details are: java.net.MalformedURLException: no protocol: www.google.com
at java.net.URL.(URL.java:593)
at java.net.URL.(URL.java:490)
at java.net.URL.(URL.java:439)
at MWE.throwMalFormedURLException(MWE.java:12)
at testMWE.testThrowMalFormedURLException(testMWE.java:12)
In the Junit console it says :
java.lang.AssertionError: Expected exception: Java.net.MalformedURLException
But the Junit is reporting failure, even though the console is telling me I've got a MalformedURLException.
What am I doing wrong with this test ?
Thanks for your thoughts.
David
You are catching the exception and therefore it is not being thrown.
If your intent is to test that you are capturing the exception and relaying it back to the 'user' properly, you should create tests for that specifically. You probably don't want UI elements in your unit tests* so this is a place where abstraction and DI have a lot of value. One simple approach is to create a mock object that will listen for the error message and mark a flag when the message is received. Your unit test trigger the error and then pass if the flag is set. You should also have a negative test or assert that the flag is not set prior to throwing the exception.
*Testing the UI is also a good idea but it can be a little slow. There are various tools for automating that. It generally falls in to a different phase of testing. You really want the unit tests to be really fast so that you can run them very frequently.
You have written production code that simply isn't testable. And more specifically: this code doesn't have any "programmatically" observable side effects in the first place.
Meaning: when you write "production code", the code within a method can do three things that could be observed:
Make method calls on objects that are fields of the class under test
Return some value
Throw an exception
For each of these options, you might be able to write testing code:
Using dependency injection, you can put a mocked object into your class under test. And then you can check that the expected methods are invoked on your mock object; with the parameter that you would expect.
You compare the result you get from calling that method with some expected value
You use expected to ensure that a specific exception was thrown
When you look at your code; you can see: it does none of that. It only operates on objects that are created within the method. It doesn't return any value. And, most importantly: it doesn't throw an exception!
Long story short: a caught exception isn't "leaving" the method. It is caught there, and the method ends normally. The fact that you print details about the caught exception doesn't change that.
So, the first thing you have to do: remove the whole try/catch from your production code!
And, if you want to have a more specific test, you can do something like:
#Test
public void testException() {
try {
new MWE().throwMalFormedURLException();
fail("should have thrown!");
} catch ( MalFormedURLException me ) {
assertThat(me.getMessage(), containsString("whatever"));
}
The above:
fails when no exception is thrown
fails when any other exception than MalFormedURLException is thrown
allows you to check further properties of the thrown exception
This is a valid test failure. The test asserts that calling throwMalFormedURLException() will throw MalformedURLException, but since you're catching the exception, it doesn't throw it, so the test fails.
Say I have a system property MY_PROP:
java -DMY_PROP="My value"
This property is necessary for my system to work.
What is the right exception to throw if this property is not set?
#PostConstruct
private void init() {
myProp = System.getProperty("MY_PROP");
if (myProp == null) {
throw new ????
}
// ...
}
Somehow IllegalArgumentException does not feel right. Maybe IllegalStateException, MissingResourceException, TypeNotPresentException? What is the standard practice for this scenario?
There is none. I would throw the IllegalStateException, because you are missing the parameter. This mean that configuration validator has failed and your application is in invalid state. In other words you should never be able to call the init() at all.
In case the value of parameter would be invalid, then i would throw an IllegalArgumentException.
If you are writing a validator, you should decide between using RuntimeException or checked one. When using for example javax.naming.ConfigurationException`, or created own one configuration exception. You API will be able to handle such exception and react properly in term of legacy.
Definitions:
IllegalStateException - Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.
IllegalArgumentException - Thrown to indicate that a method has been passed an illegal or inappropriate argument.
I only add to Vash's answer for the Spring Framework. If your using the Spring Framework and you want to be consistent with how most of the components in Spring do it then I would say you should use IllegalStateException (or your own derivation).
In Spring most components that do a #PostConstruct or #Override void afterPropertiesSet() throw IllegalStateException using the util org.springframework.util.Assert.state(..).
You can see this done in Spring AMQP as one example.
That being said I have actually filed bugs against Spring MVC where they used IllegalArgumentException instead of a custom and more explicit derived class. With static inline classes its very easy to create a custom exception with out creating another Java file.
Because a system property is not always defined, the standard pratice is to use a default value when you can't find the property.
I just checked some standard code in java 7 (apache tomcat, java.lang, java.awt, ...), they always use a default "fallback" when the property is null.
So maybe your problem is somewhere else ?
Why don't you take this parameters as a required argument of your jar ? Then you can use IllegalArgumentException.
I am learning mockito and unit testing.This is my constructor. To test the constructor that it throws jparse exceptions, I have a test method. Why do we generate our own exception and assert it. How is it testing? What are we testing here? Please help!
public ClassA(File file) throws JsonParseException,
JsonMappingException, IOException {
ObjectMapper json= new ObjectMapper();
Map<String, String>> readValue= mapper.readValue(file,
Map.class);
..........
}
#Test(expected = JsonParseException.class)
public void testCorruotionInContent() throws Exception {
ObjectMapper json= Mockito.mock(ObjectMapper.class);
PowerMockito.whenNew(ObjectMapper.class).withNoArguments()
.thenReturn(json);
Mockito.when(
mapper.readValue(Mockito.any(File.class), Mockito.eq(Map.class)))
.thenThrow(new JsonParseException(null, null));
new ClassA(Mockito.mock(File.class));
}
Your test is fragile - as pointed out in comments, you're not testing anything about a concrete implementation, but rather the mock. I'm not even convinced you're testing anything at all.
Remember: you assert against concrete data; you mock what you absolutely need to.
Given that I don't know the full implementation of Constructor, I don't know what it'd take to cause it to fail. I do know, however, there are at least three conditions in which it would fail:
Some kind of IOException - likely the file doesn't exist or can't be read
Some kind of JsonMappingException - the object can't be mapped to JSON
Some kind of JsonParseException - the JSON entity can't be parsed
It is good practice to test all of these conditions, to ensure that your code behaves appropriately when any of these exceptions come up. If you don't expect your code to handle it, then it is acceptable for it to throw these exceptions, and when such a situation occurs in your code, you are verifying that the exception was actually thrown.
But how do we get to that? Let's start off simple.
Suppose we mocked out the instance of the File, and whenever/wherever we decided to read it, we'd get back a string of invalid JSON. That would be a sufficient case to test against - we can't create a file on the host file system (not worth the headache to spin up different files, so simply mocking them out would be acceptable), but we can dictate the data coming from the file.
(In the time I've written this answer, you've changed the class name from Constructor to Class. That's not going to fly - there's already a Class object.)
I have a class that contains a cache (Set), and the cache is built on instantiation. I'm confused which exception/error should I throw if building cache fail (cannot connect to database or some).
class Provider {
public Provider() {
buildCache();
}
private void buildCache() {
try {
this.cache = getDataFromDb();
} catch (Exception ex) {
throw new ???
}
}
}
One exception comes in my mind is ExceptionInInitializerError, but javadoc says it is thrown on initialize static members.
Should I throw an IllegalStateException cause the cache isn't built so this class is useless?
Clearly I can create my own ErrorOnBuildingCache and throw it but I wonder if any exception in Java library suits this circumstance.
If you're in doubt as to which exception should be thrown, then so will users of your code. So define your own exception type (e.g. FailedToInitializeCacheException) and throw that. No ambiguity that way.
IllegalStateException would be a reasonable fallback position, but you should never, ever use ExceptionInInitializerError (or anything ending in Error) - that's low-level classloader stuff, don't mess with that.
Clearly I can create my own
ErrorOnBuildingCache and throw it but
I wonder if any exception in Java
library suits this circumstance.
This is exactly what you should do. Do not try to use an existing exception, but instead make one of your own. So you know when it is throwed that it is related to your cache and not a static field instanciation error or something.
On a side note, you shouldn't catch exception excepted in very specific cases. Catching exception will catch everything like null pointer exceptions, divide by zero, IO errors, security exception.
What I would do is:
Include the cause when rethrowing the
exception to allow better
investigation
Catch exceptions that could occurs
due to IO/Network problems but
associate them with the right error
message. In you case this is DB exceptions.
Do not catch exception that are due
to programming bugs (like null
pointers), let them popup so you
directly know the real error cause.