Hey all I am trying to get these Unit tests to fail but can't it uses annotations, which is new to me. Any ideas would be great!
I have been trying all sorts of ways to get them to fail by either setting the test class variables to null, or trying to use if/else statements in the minimum test, but they always come out passing. Is this correct?
public class ValidationServiceTest extends BaseServiceTest {
ValidationService validationService;
ValidationException ve;
TestDto test;
Field f;
#Before
public void setup() {
validationService = new ValidationService();
ve = null;
}
#Test
public void validateNotNull(){
try {
validationService.validate(ve, test.xx);
assertNotNull("testing notNull()", ve);
} catch (Exception e) {
}
}
#Test
public void validateMin(){
try {
validationService.validate(ve, test.xy);
if(test.xy > f.min()){
assertTrue("testing min()" , test.xy > -1);
}
} catch (Exception e) {
}
}
public class TestDto{
#Field(notNull=true)
public Integer xx = null;
#Field(min=2)
public Integer xy = -5;
}
}
Do not catch Exception, mark test method with throws Exception instead.
The test field is never initialized in your test, which means it's null. This causes NullPointerException whenever you try to access fields of test. The assertion line is skipped and exception is suppressed in the catch clause. Removing the try/catch block and marking test method with throws Exception instead will cause the test to report error and you will see what's wrong instantly.
Related
I need to throw a couple times a custom exception. A test class is checking if my solution works but I'm not allowed to make any changes to this class which leads me to my problem.
I simplified the problem here, because the whole code is not needed here
public class Test{
public static final String s = "0test";
#Test
public void testZero(){
Solver sol = new Solver(Parser.run(s));
//IntelliJ is underlining "run" because "Unhandled exception: ParseException", a
//simple solution could be adding "throws ParseException" in the head, but I'm not
//allowed to change the test class
}
}
public class Parser{
public static Pars run(String input) throws ParseException{
if(input.charAt(0) == '0'){
throw new ParseException("...");
}
}
}
public class ParseException extends Exception{
public ParseException(String mess){
super(mess);
}
}
I'm not allowed to make any changes to this class which leads me to my problem.
There is no way that you can throw an Exception to the Test class without catching it over there.
BUT you can prematurely just catch it inside the Parser#run(String input).
Instead of this:
public static Pars run(String input) throws ParseException{
if(input.charAt(0) == '0'){
throw new ParseException("...");
}
}
You could (as I said) catch it in the method instead.
public static Pars run(String input) {
try {
if(input.charAt(0) == '0'){
throw new ParseException("...");
}
} catch (ParseException e) {
// System.out.println(e.toString());
// Just handle it over here if you can't edit Test.java ...
}
}
I have found the solution for my problem.
In my ParseException class, I need to change it to:
public class ParseException extends IllegalArgumentException{...}
Further into the task, the test class didnt accept my exception because there was a IllegalArgumentException exspected.
Changing it into "extends IllegalArgumentException" solves the problem, so I dont need "throws ParseException" in the headings and no try,catch statements
From a single method trowing two different custom exceptions based on the condition. While creating a custom exception passing two things one is an error message and another one is error code as a string. But I'm unable to get the error based on the error code. getting an error while calling processErrorCodes() method. Could anyone please help me in fixing this.
// BackgroundException is a custom EXCEPTION
public class BackgroundException extends Exception {
private static final long serialVersionUID = 4664456874499611218L;
private String errorCode="Unknown_Exception";
public BackgroundException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
// Similarly I have InvalidException custom exception
public class MyExceptionTest {
public void methodTest(){
String policyId =null;
String policyNotification = null;
String policyStatus = null;
try {
if(policyNotification !=null) {
if(policyStatus!=null) {
if(policyId!=null) {
}
else{
throw new InvalidException("Policy ID Is Null","POLICY_ID");
}
}else{
throw new BackgroundException("Policy Status Is Null","POLICY_STATUS");
}
}
else{
throw new BackgroundException("Policy Notification Is Null","POLICY_NOTIFICATION");
}
} catch (BackgroundException | InvalidException e ) {
// TODO Auto-generated catch block
try {
processErrorCodes(e);
} catch (MyExcep e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.getMessage();
}
}
private static void processErrorCodes(Exception e) throws BackgroundException,InvalidException {
switch(e.getErrorCode()){
case "POLICY_NOTIFICATION":
System.out.println(e.getMessage());
throw e;
case "POLICY_ID":
System.out.println(e.getMessage());
throw e;
case "POLICY_STATUS":
System.out.println(e.getMessage());
throw e;
default:
System.out.println("Unknown exception occured, lets log it for further debugging."+e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
MyExceptionTest mt = new MyExceptionTest();
mt.methodTest();
}
}
I just want to handle those exceptions based on the error code.
You need a common superclass for all your custom exceptions, let say MessageCodeException, extending Exception and the accept this super class type as a parameter inside of your processErrorCodes method
public abstract class MessageCodeException extends Exception {
public abstract String getCode();
// you can have a same abstract method for message
}
public class BackgroundException extends MessageCodeException {
// ...
}
public class InvalidException extends MessageCodeException {
// ...
}
//and now the process method will look like
private static void processErrorCodes(Exception e) throws ... {
// ...
}
That's abvious that for current implementation you cannot access code field, because Exception class interface does not provide anything like this
BTW it seems to be very bad idea to create Exception driven business validation logic. Wouldn't it be better to create some kind of ValidationResult object with list (lists) of errors/warning/successes and to process such validation result at the end? The purpose of the Exception existence is not to control application flow, but to force user to provide some support for critical situations (or to handle somehow unexpected situations with RuntimeException)
I would like to test the return code of an exception. Here is my production code:
class A {
try {
something...
}
catch (Exception e)
{
throw new MyExceptionClass(INTERNAL_ERROR_CODE, e);
}
}
And the corresponding exception:
class MyExceptionClass extends ... {
private errorCode;
public MyExceptionClass(int errorCode){
this.errorCode = errorCode;
}
public getErrorCode(){
return this.errorCode;
}
}
My unit test:
public class AUnitTests{
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test (expected = MyExceptionClass.class,
public void whenRunningSomething_shouldThrowMyExceptionWithInternalErrorCode() throws Exception {
thrown.expect(MyExceptionClass.class);
??? expected return code INTERNAL_ERROR_CODE ???
something();
}
}
Simple:
#Test
public void whenSerialNumberIsEmpty_shouldThrowSerialNumberInvalid() throws Exception {
try{
whenRunningSomething_shouldThrowMyExceptionWithInternalErrorCode();
fail("should have thrown");
}
catch (MyExceptionClass e){
assertThat(e.getCode(), is(MyExceptionClass.INTERNAL_ERROR_CODE));
}
That is all you need here:
you don't want to expect that specific exception, as you want to check some properties of it
you know that you want to enter that specific catch block; thus you simply fail when the call doesn't throw
you don't need any other checking - when the method throws any other exception, JUnit will report that as error anyway
You can check for it using hamcres matchers as long as thrown.expect is overload to receive Matcher
thrown.expect(CombinableMatcher.both(
CoreMatchers.is(CoreMatchers.instanceOf(MyExceptionClass.class)))
.and(Matchers.hasProperty("errorCode", CoreMatchers.is(123))));
Note that you will need to add hamcrest matcher to your dependencies. Core matched that are included in JUnit is not enough.
Or if you don't want to use CombinableMatcher:
thrown.expect(CoreMatchers.instanceOf(MyExceptionClass.class));
thrown.expect(Matchers.hasProperty("errorCode", CoreMatchers.is(123));
Also, you don't need (expected = MyExceptionClass.class) declaration for #Test annotation
Expanding upon Sergii's answer, you can clean this up even more by writing a custom matcher.
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
public class CustomMatcher extends TypeSafeMatcher<CustomException> {
public static CustomMatcher hasCode(String item) {
return new CustomMatcher(item);
}
private String foundErrorCode;
private final String expectedErrorCode;
private CustomMatcher(String expectedErrorCode) {
this.expectedErrorCode = expectedErrorCode;
}
#Override
protected boolean matchesSafely(final CustomException exception) {
foundErrorCode = exception.getErrorCode();
return foundErrorCode.equalsIgnoreCase(expectedErrorCode);
}
#Override
public void describeTo(Description description) {
description.appendValue(foundErrorCode)
.appendText(" was not found instead of ")
.appendValue(expectedErrorCode);
}
}
The error code can then be checked like:
import org.junit.rules.ExpectedException;
public class MyObjTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void someMethodThatThrowsCustomException() {
thrown.expect(CustomException.class);
thrown.expect(CustomMatcher.hasCode("110501"));
MyObj obj = new MyObj();
obj.methodThatThrowsCustomException();
}
}
Reference: https://dzone.com/articles/testing-custom-exceptions
Let me explain what I exactly expecting
I have a method like the following
public void removeByObject()
{
try {
DsrCollection dsrCollection = new DsrCollection();
dsrCollection. setNuId(180);
dsrCollectionRepository.remove(dsrCollection);
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
Here I want to check that the particular method removeByObject() executed successfully or not(also want to involve Assert.assertEqual(dsrCollectionRepository.remove(dsrCollection),??)). So for checking the condition what should be the actual value.
Or in a more specific way what object should appear in actual value place. My requirement is like if application failed to execute dsrCollectionRepository.remove(dsrCollection) it should return the assertError message
To make removeByObject() more testable you can simply extract the code in the try block into its own method. e.g.:
public class DsrCollectionRepositoryManager /* Or whatever your class is called. */ {
/* ... */
public void removeByObject() {
try {
removeByObjectOrThrow();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
protected boolean /* or whatever your return type is */ removeByObjectOrThrow() {
DsrCollection dsrCollection = new DsrCollection();
dsrCollection.setNuId(180);
return dsrCollectionRepository.remove(dsrCollection);
}
/* ... */
}
Now you can test removeByObjectOrThrow() and see if it throws an exception or not.
If you are trying to test it where removeByObject() is called on your behalf and/or you don't want to call removeByObjectOrThrow() directly then you can subclass your unit under test. e.g.:
public class DsrCollectionRepositoryManagerTest {
#Test
public void removeObjectSuccessful() {
boolean expected = true;
DsrCollectionRepositoryManager dsrCollectionRepositoryManager = new DsrCollectionRepositoryManager() {
#Override
protected boolean removeByObjectOrThrow() {
try {
boolean actual = super.removeByObjectOrThrow();
Assert.assertEquals(actual, expected);
return actual;
} catch (Exception cause) {
String message = "`removeObject` should not have thrown an exception but did";
throw new AssertionError(message, cause);
}
}
};
dsrCollectionRepositoryManager.removeByObject();
}
#Test
public void removeObjectUnsuccessful() {
DsrCollectionRepositoryManager dsrCollectionRepositoryManager = new DsrCollectionRepositoryManager() {
#Override
protected boolean removeByObjectOrThrow() {
super.removeByObjectOrThrow();
String detailMessage = "`removeByObject` should have thrown an exception but did not";
throw new AssertionError(detailMessage);
}
};
dsrCollectionRepositoryManager.removeByObject();
}
}
As I don't know the name of your unit under test nor the type of what you want to use assertEquals with I've made things up but the idea is the same: isolate the code you want to test and test it.
Does dsrCollectionRepository.remove(obj) return a value indicating whether the removal is successful or not? I'd recommend implementing the function so it does return a boolean on a successful removal of an object, otherwise you rely on exceptions to inform you of the failure of the function.
If it already returns a boolean value just assertTrue(dsrCollectionRepository.remove(dsrCollection);
If the failure of the function throws a known exception you can use the following annotation to test the function:
#Test(expectedExceptions = MyException.class), however you then rely on the fact that only that exception can be thrown while performing that function, which is problematic if someone adds an exception that can be thrown in implementation without your knowledge.
I have been trying to run the following test using mockito and junit and I keep on getting "java.lang.NullPointerException: name must not be null"
Can anyone tell me why this is happening?
On debugging, I found out that this exception is thrown when the test executes the following statement in isStopValid(String) method:
FacilityValidationUtil facUtil = new FacilityValidationUtil();
#RunWith(MockitoJUnitRunner.class)
public class MyFormTest{
#InjectMocks MyForm form = new MyForm();
#Mock FacilityValidationUtil facUtil;
#Test
public void testIsStopValid() throws FinderException{
when(facUtil.isFacilityValid("")).thenReturn(false);
form.setOrigin("");
assertEquals(false, form.isStopValid(form.getOrigin()));
}
}
Class with method to be tested:
public class MyForm{
FacilityValidationUtil facUtil = new FacilityValidationUtil();
public boolean isStopValid(String stop){
try {
return facUtil.isFacilityValid(stop);
} catch (FinderException e) {
log.error("Error finding the stop. "+e.getCause());
return false;
}
}
}
public class FacilityValidationUtil{
private FacilityDAO facilityDao = new HibernateFacilityDAO();
public boolean isFacilityValid(String facility) throws FinderException{
boolean test;
FacilityImpl facilityImpl = facilityDao.findFacilityByNassCode(facility);
test = (facilityImpl==null)?false : true;
return test;
}
}
public class HibernateFacilityDAO extends HibernateAbstractDeltaDAO implements FacilityDAO {
public HibernateFacilityDAO() {
super(false);
}
}
Short Answer: You are trying to mock a variable (facUtil) that is local to your isStopValid method, so the mock version of this object in your test is never going to be called because you are 'newing it up" each time.
Long Answer: It looks like you are trying to mock the call to your FacilityValidationUtil class, and if this is the case, then you need to either make the class a field so that Mockito can inject the object by reflection (if this object is thread safe, which it looks like it is) or explore a mocking framework like PowerMockito that will allow you to mock a constructor (google for PowerMockito when new).
PowerMockito.whenNew(FacilityValidationUtil.class).withNoArguments().thenReturn(facUtil);
Mockito doesn't support any mocking of constructor args by default.
EDIT
If you are still having trouble, then I would suggest starting with a smaller example. I've put together one for you that works and uses the code you are trying to test (It's using inner classes though, which Mockito has some quirky rules about, but I'm just doing it to compress the example).
#RunWith(MockitoJUnitRunner.class)
public class MyFormTest {
#InjectMocks
private MyForm form = new MyForm();
#Mock
private FacilityValidationUtil facUtil;
#Test
public void testIsStopValid_false() {
when(facUtil.isFacilityValid("")).thenReturn(false);
assertEquals(false, form.isStopValid(""));
}
#Test
public void testIsStopValid_true() {
when(facUtil.isFacilityValid("")).thenReturn(true);
assertEquals(true, form.isStopValid(""));
}
public class MyForm {
private FacilityValidationUtil facUtil = new FacilityValidationUtil();
public boolean isStopValid(String stop) {
try {
return facUtil.isFacilityValid(stop);
} catch (FinderException e) {
return false;
}
}
}
public class FacilityValidationUtil {
public boolean isFacilityValid(String facility) throws FinderException {
throw new RuntimeException(facility);
}
}
public class FinderException extends RuntimeException {
public FinderException(String message) {
super(message);
}
}
}
What's really important is that your mock is not getting injected correctly. Until you get that resolved, you are going to keep getting the same error. Set a break point in your MyForm at the point you call facUtil.isFaciltyValid and look at the object. It should be a mockito object, not your class.
Good luck.