I have a class which I have annotated as #injectMock. This class has a constructor which loads messages from in put stream as below:
public class RegistrationEventValidator {
private Properties validationMessages;
RegistrationEventValidator() {
validationMessages = new Properties();
try {
validationMessages.load(RegistrationEventValidator.class.getClassLoader().getResourceAsStream("ValidationMessages.properties"));
} catch (IOException e) {
throw new InternalErrorException("Failed loading ValidationMessages.properties");
}
}
}
My test covers up until the "catch exception". How do I unit test that part? Thank you.
This is what I have so far and I am getting this error: "org.opentest4j.AssertionFailedError: Expected com.autonation.ca.exception.InternalErrorException to be thrown, but nothing was thrown"
#Test
void test_validation_messages_properties() throws IOException {
//given
List<String> errors = new ArrayList<>();
Event<AuthEventDetails> event = new Event<>();
AuthEventDetails request = new AuthEventDetails();
event.setCustomerId(RandomStringUtils.random(65));
request.setFirstName(RandomStringUtils.random(256));
request.setLastName(RandomStringUtils.random(256));
event.setEventDetails(request);
doThrow(new InternalErrorException("Failed loading ValidationMessages.properties")).when(validationMessages).load(any(InputStream.class));
assertThrows(InternalErrorException.class, () -> registrationEventValidator.validate(event, errors));
}
Related
I am trying to write some unit tests to see if a logging method gets called for csv exceptions. The flow goes something like this:
CsvToBean is used to parse some info and each bean that is produced has some work done on it.
After all this, CsvToBean.getCapturedExceptions().forEach() is used to processed the exceptions.
How to I create some of these exceptions for testing?
public void parseAndSaveReportToDB(Reader reader, String reportFileName,ItemizedActivityRepository iaRepo,
ICFailedRecordsRepository icFailedRepo,
String reportCols) throws Exception {
try {
CsvToBean<ItemizedActivity> csvToBean = new CsvToBeanBuilder<ItemizedActivity>(reader).withType(ItemizedActivity.class).withThrowExceptions(false).build();
csvToBean.parse().forEach(itmzActvty -> {
itmzActvty.setReportFileName(reportFileName);
String liteDesc = itmzActvty.getBalanceTransactionDescription();
if (liteDesc.contains(":")) {
liteDesc = liteDesc.substring(liteDesc.indexOf(":")+1).trim();
}
itmzActvty.setLiteDescription(liteDesc);
itmzActvty.setAmount(convertCentToDollar(itmzActvty.getAmount()));
iaRepo.save(itmzActvty);
});
log.info("Successfully saved report data in DB");
csvToBean.getCapturedExceptions().forEach(csvExceptionObj -> logFailedRecords(reportFileName, csvExceptionObj, icFailedRepo, reportCols));
reader.close();
} catch (Exception ex) {
log.error("Exception when saving report data to DB", ex);
throw ex;
}
}
In this code I need to trigger the logFailedRecords method. To do so I need to fill the captured exceptions queue with an exception. I don't know how to get an exception in there.
What I have is not much since I keep hitting walls
#Test
public void testParseAndSaveReportToDBWithExceptions() throws Exception {
// CsvException csvExceptionObject = new CsvException("testException");
CsvToBean<ItemizedActivity> csvToBean = mock(CsvToBean.class);//<ItemizedActivity>(reader).withType(ItemizedActivity.class).withThrowExceptions(false).build().class);
BufferedReader reader = mock(BufferedReader.class);
ReportingMetadata rmd = this.getReportingMetadata();
verify(this.reportsUtil).parseAndSaveReportToDB(reader,"test.csv",
this.iaRepo,this.icFailedRepo,rmd.getReportCols());
// System.out.println(csvToBean.getCapturedExceptions().toString());
}
I have ran this code and the screenshot gets captured after the chrome browser closes (#After)
If i comment out CloseBrowser(); the screenshot gets captured but the chromebrowser stay open.
I want the screenshot to capture on a failed test then close the browser.
in summary
The screenshot currently captures after the browser closes, which is just a blank .png
I want the screenshot to capture when a test fails just before the browser closes
Thanks
public class TestClass extends classHelper//has BrowserSetup(); and CloseBrowser(); {
#Rule
public ScreenshotTestRule my = new ScreenshotTestRule();
#Before
public void BeforeTest()
{
BrowserSetup();// launches chromedriver browser
}
#Test
public void ViewAssetPage()
{
//My test code here//And want to take screenshot on failure
}
#After
public void AfterTest() throws InterruptedException
{
CloseBrowser();//closes the browser after test passes or fails
}
}
class ScreenshotTestRule implements MethodRule {
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
statement.evaluate();
} catch (Throwable t) {
captureScreenshot(frameworkMethod.getName());
throw t; // rethrow to allow the failure to be reported to JUnit
}
}
public void captureScreenshot(String fileName) {
try {
new File("target/surefire-reports/").mkdirs(); // Insure directory is there
FileOutputStream out = new FileOutputStream("target/surefire-reports/screenshot-" + fileName + ".png");
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));
out.close();
} catch (Exception e) {
// No need to crash the tests if the screenshot fails
}
}
};
}
}
You can implement TestNG Listeners to execute code before a test or after a test
Or when a test fails or succeeded etc.
Implement it like below and put your screenshot in the method i showed
public class Listeners implements ITestListener {
Methods…
And put the screenshot code inside the method below:
#Override
public void onTestFailure(ITestResult result) {
code for screenshot
}
}
So i have found a way to implement the screenshots. I have created a method that will take a screenshot. I have put a try and catch around my test code and catch an exception and calling the method to take a screenshot.
public class TestClass extends classHelper//has BrowserSetup(); and CloseBrowser(); {`
#Rule
public ScreenshotTestRule my = new ScreenshotTestRule();
#Before
public void BeforeTest()
{
BrowserSetup();// launches chromedriver browser
}
#Test
public void ViewAssetPage()
{
try
{
//My test code here//And want to take screenshot on failure
}
catch(Exception e)
{
//print e
takeScreenShot();
}
}
#After
public void AfterTest() throws InterruptedException
{
CloseBrowser();//closes the browser after test passes or fails
}
}
///////////////////////////////////////////
void takeScreenShot()
{
try
{
int num = 0;
String fileName = "SS"+NAME.getMethodName()+".png";//name of file/s you wish to create
String dir = "src/test/screenshot";//directory where screenshots live
new File(dir).mkdirs();//makes new directory if does not exist
File myFile = new File(dir,fileName);//creates file in a directory n specified name
while (myFile.exists())//if file name exists increment name with +1
{
fileName = "SS"+NAME.getMethodName()+(num++)+".png";
myFile = new File(dir,fileName);
}
FileOutputStream out = new FileOutputStream(myFile);//creates an output for the created file
out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES));//Takes screenshot and writes the screenshot data to the created file
//FileOutputStream out = new FileOutputStream("target/surefire-reports/" + fileName);
out.close();//closes the outputstream for the file
}
catch (Exception e)
{
// No need to crash the tests if the screenshot fails
}
This might help:
https://github.com/junit-team/junit4/issues/383
The ordering for rule execution has changed with new 'TestRule'
So I'm testing a AccountService class with a mocked databaselayer.
In this AccountService class there is a private method that checks the input received from UI according to a regex.
The positive test I wrote is working fine:
#Test
public void testEmailPatroonCorrect() throws Exception{
//Correcte emails
List<String> emails = new ArrayList<>();
emails.add("user#domain.com");
emails.add("user#domain.co.in");
emails.add("user.name#domain.com");
emails.add("user_name#domain.com");
emails.add("username#yahoo.corporate.in");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
assertThatCode(() -> {
for(String email : emails){
method.invoke(AccountService,email);
}}).doesNotThrowAnyException();
}
However for the negative test (a list with wrong email patterns) even with only one object in the list for simplicity
#Test
public void testEmailPatroonFout() throws Exception{
//Verkeerde emailpatronen
List<String> emails = new ArrayList<>();
emails.add(".username#yahoo.com");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
assertThatThrownBy(()->{
for(String email : emails){
method.invoke(AccountService,email);
}
}).isInstanceOf(ApplicationException.class).hasMessage(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg());
}
The exception thrown during test is: java.lang.reflect.InvocationTargetException. In the application the ApplicationException gets caught just fine.
Question is how can I write a proper test for a list of wrong email patterns? (without using #VisibleForTesting functionality since it's a school project).
Many thanks!
The InvocationTargetException wraps the exception thrown within the reflectively invoked method. So you may catch the InvocationTargetException and rethrow its cause, but I’d put that into a utility method, like
public interface TestMethod<D,A> {
void invoke(D d, A a) throws Throwable;
}
static <D,A> TestMethod<D,A> method(
Class<D> declarer, String name, Class<A> argType) throws ReflectiveOperationException {
Method method = declarer.getDeclaredMethod(name, argType);
method.setAccessible(true);
return (d,a) -> {
try {
method.invoke(d, a);
} catch(InvocationTargetException ex) {
throw ex.getTargetException();
}
};
}
which you can use like
#Test
public void testEmailPatroonFout() throws Exception{
//Verkeerde emailpatronen
List<String> emails = new ArrayList<>();
emails.add(".username#yahoo.com");
TestMethod<AccountService, String> method
= method(AccountService.class, "checkEmailPatroon", String.class);
assertThatThrownBy(() -> {
for(String email : emails){
method.invoke(AccountService, email);
}
}).isInstanceOf(ApplicationException.class)
.hasMessage(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg());
}
The shape of the TestMethod interface allows the alternative implementation like
static <D,A> TestMethod<D,A> method(
Class<D> declarer, String name, Class<A> argType) throws ReflectiveOperationException {
Method method = declarer.getDeclaredMethod(name, argType);
method.setAccessible(true);
return MethodHandleProxies.asInterfaceInstance(
TestMethod.class, MethodHandles.lookup().unreflect(method));
}
Thanks to Holger I was able to write a working test for it's purpose.
#Test
public void testEmailPatroonFoutLoop() throws Throwable {
//Verkeerde emailpatronen
List<String> wrongEmails = new ArrayList<>();
wrongEmails.add(".username#yahoo.com");
wrongEmails.add("username#yahoo.com.");
wrongEmails.add("usernameyahoo.com");
wrongEmails.add("username#yahoo.c");
wrongEmails.add("use..rname#yahoo.com");
Class<AccountService> foo = AccountService.class;
Method method = foo.getDeclaredMethod("checkEmailPatroon", String.class);
method.setAccessible(true);
int countedWrongEmails = 0;
for(String email : wrongEmails){
try{
method.invoke(accServ,email);
}
catch (InvocationTargetException ie){
Exception e = (Exception) ie.getTargetException();
if(e.getMessage().equals(ApplicationExceptionType.ONGELDIGE_EMAIL.getMsg())){
countedWrongEmails++;
}
}
}
assertThat(countedWrongEmails).isEqualTo(wrongEmails.size());
}
Although I see the benefits and elegance of writing a TestMethod interface, I however do not yet possess the knowledge to grasp it's complexity. So I will stick to this test that I'll be able to explain on the verbal exam.
I have a method called doParallelThings:
public Dummy doParallelThings(Map<String, String> mapp) throws Exception {
Dummy dummy = new Dummy();
CompletableFuture<Ans1> one = firstService.getOne(mapp.get("some1"), mapp);
CompletableFuture<Ans2> two = secondService.getTwo(headersMap.get("some2"), mapp);
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(one, two);
try {
combinedFuture.get();
dummy.setOne(one.get());
dummy.setTwp(two.get());
} catch (Throwable e) {
}
return dummy;
}
Code works fine but when I'm trying to test it,
combinedFuture.get(); goes to infinite loop.
Unit test is as below:
#Mock
private CompletableFuture<Void> ans;
#Test
public void testDoParallelThings() throws Exception {
PowerMockito.mockStatic(CompletableFuture.class);
PowerMockito.when(CompletableFuture.allOf(any())).thenReturn(ans);
when(ans.get()).thenReturn(null);
Dummy dummy = dummyService. doParallelThings(mockMap);
assertNotNull(dummy);
}
I have also added #RunWith(PowerMockRunner.class)
#PrepareForTest({CompletableFuture.class}) above the test class.
What am I missing?
when(firstService.getOne(any(), any())).thenReturn(CompletableFuture.completedFuture(mockOne));
solved my problem
I need to test a service by JUnit.
Here is my code :
public class AdviesBoxTestDaoImpl {
private SearchDaoImpl searchDaoImpl;
private SearchParametersDto searchParametersDto;
JSONObject jsonObject;
#Before
public void loadJsonFile(){
try{
ObjectMapper mapper = new ObjectMapper();
searchParametersDto = mapper.readValue(new File("D:\\productsData.json"), SearchParametersDto.class);
}
catch(Exception e){
}
}
#Test
public void testsDemoMethod() throws SQLException {
System.out.println(searchParametersDto.toString());
assertEquals( "Products saved successfully",
searchDaoImpl.inTable(searchParametersDto));
}
}
Result of my service is message as "Products saved successfully" in String which is I am comparing here. Each time I run the test case , I get the NullPointerException Error.
What changes I should make in the code so that I can test the service correctly?
You should not catch the exception in the loadJsonFile() method. It hides any exception and you don't see the real cause of failing tests. Here is an improved loadJsonFile().
#Before
public void loadJsonFile() throws Exception {
ObjectMapper mapper = new ObjectMapper();
searchParametersDto = mapper.readValue(
new File("D:\\productsData.json"),
SearchParametersDto.class
);
}