JUnit 5 - JDBC statements testing - java

I've begun learning unit tests. I'm working with JUnit 5 and I'd like to test my method that inserts some data into my database (using JDBC). Here's my code:
Datasource.java
import java.sql.*;
public class Datasource {
public static final String CONNECTION = "jdbc:mysql://127.0.0.1:3306/java";
private Connection connection;
public boolean open() {
try {
connection = DriverManager.getConnection(CONNECTION, "root", "");
return true;
} catch (SQLException e) {
System.out.println(e.getMessage());
return false;
}
}
public boolean insertTable() {
try {
String query = "INSERT INTO artists(name) VALUES(?)";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, "Test");
int result = stmt.executeUpdate();
if (result == 1) return true;
return false;
} catch (SQLException e) {
System.out.println(e.getMessage());
return false;
}
}
}
DatasourceTest.java
import static org.junit.jupiter.api.Assertions.*;
class DatasourceTest {
private Datasource datasource;
#org.junit.jupiter.api.BeforeEach
void setUp() {
datasource = new Datasource();
if (!datasource.open()) {
System.exit(-1);
}
}
#org.junit.jupiter.api.Test
void insertTable() {
assertTrue(datasource.insertTable());
}
}
It works fine but it actually inserts a record into my database, but I what I want to do is to simulate it. Is it possible to achieve that using only JUnit? If not, what do I need? And a simple implementation would be highly appreciated.
EDIT
I found out about a tool called Mockito, is it what I need? If so, could anyone show me how to deploy a simple test of my method insertTable()?

This is what I did using mockito to test insetTable method
import static org.junit.Assert.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
#RunWith(MockitoJUnitRunner.class)
public class DatasourceTest {
#InjectMocks
Datasource datasource;
#Mock
Connection connection;
#Mock
PreparedStatement stmt;
#Before
public void setUp() throws SQLException {
when(connection.prepareStatement(eq("INSERT INTO artists(name) VALUES(?)"))).thenReturn(stmt);
when(stmt.executeUpdate()).thenReturn(1);
}
#Test
public void testInsertTable() {
assertTrue(datasource.insertTable());
}
}

You can use the DbUnit framework with an H2 or HSQL Memory Database.
You will open real connections to a memory Database and you could check that the records is saved by using DataSets

So If using PowerMockito with version 1.6.5 I would test your code as following
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Datasource.class, DriverManager.class, Connection.class })
public class DatasourceTest {
#Mock
Connection con;
#Mock
PreparedStatement ps;
#Test
public void insertTableTest() throws Exception {
PowerMockito.mockStatic(DriverManager.class);
PowerMockito.when(DriverManager.getConnection(
Mockito.eq("jdbc:mysql://127.0.0.1:3306/java"),
Mockito.eq("root"),
Mockito.eq(""))).thenReturn(con);
Datasource ds = Mockito.mock(Datasource.class);
PowerMockito.doCallRealMethod().when(ds).open();
PowerMockito.doCallRealMethod().when(ds).insertTable();
boolean result = ds.open();
Assert.assertTrue(result);
Mockito.when(con.prepareStatement(Mockito.eq("INSERT INTO artists(name) VALUES(?)"))).thenReturn(ps);
Mockito.when(ps.executeUpdate()).thenReturn(1);
result = ds.insertTable();
Assert.assertTrue(result);
Mockito.verify(ps).setString(Mockito.eq(1), Mockito.eq("Test"));
Mockito.verify(ps).executeUpdate();
Mockito.verify(con).prepareStatement(Mockito.eq("INSERT INTO artists(name) VALUES(?)"));
}
}
Hope this helps.

Related

JUnit mockMVC testing spring controller classes that use hibernate. Table not mapped exceptions thrown

I'm trying to create JUnit tests for spring framework controller classes.
The class im trying to test uses hibernate/HQL to pull data from a MySQL database.
What I'm trying to test is given different parameters for the HQL, it should return specific data from the database, in this case flights.
While it does start, the test throws an exception once it tries to execute the query with
org.hibernate.hql.internal.ast.QuerySyntaxException: <tablename> is not mapped
Here is the JUnit class:
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
public class SearchTest {
private MockMvc mockMvc;
private AjaxSearchController ajaxS;
#Before
public void setup() throws Exception {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
ajaxS = new AjaxSearchController();
this.mockMvc = standaloneSetup(ajaxS).setViewResolvers(viewResolver).build();
}
#Test
public void testSearch() {
String recommendation = " ";
String departure = "Perth, Australia";
String arrival = "Melbourne, Australia";
String departureDate = "2018-09-27";
try {
mockMvc.perform(post("/ajax")
.param("recommendation", recommendation)
.param("departure", departure)
.param("arrival", arrival)
.param("departureDate", departureDate));
} catch (Exception e) {
e.printStackTrace();
}
}
}
The tests are being run out of the projectname.test directory.
The controller class works fine outside of JUnit, when the webapp is run normally.
How can I get hibernate to see the entity classes it needs for these tests.
Edit:
Trying to get the web application context working.
the config.xml file is located in test/resources.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
#RunWith(SpringRunner.class)
#WebAppConfiguration
#ContextConfiguration("classpath: config.xml")
public class SearchTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void testSearch() {
String recommendation = " ";
String departure = "Perth, Australia";
String arrival = "Melbourne, Australia";
String departureDate = "2018-09-27";
try {
mockMvc.perform(post("/ajax")
.param("recommendation", recommendation)
.param("departure", departure)
.param("arrival", arrival)
.param("departureDate", departureDate));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Gives the following error:
java.io.FileNotFoundException: class path resource [ config.xml] cannot be opened because it does not exist

#Value returning null in unit test

I have a spring boot app with an Endpoint Test Configuration class and a unit test to test my http client. I am trying to get my server address and port from my application.properties which is located in my src/test.(All the classes are in my src/test.)
Here is my config class code :
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import javax.xml.bind.JAXBException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import com.nulogix.billing.service.PredictionEngineService;
import com.nulogix.billing.ws.endpoint.AnalyzeEndPoint;
import com.nulogix.billing.ws.endpoint.GetVersionEndPoint;
#Configuration
public class EndPointTestConfiguration {
#Value("${billing.engine.address}")
private String mockAddress;
#Value("${billing.engine.port}")
private String mockPort;
#Bean
public String getAddress() {
String serverAddress = "http://" + mockAddress + ":" + mockPort;
return serverAddress;
}
#Bean
public GetVersionEndPoint getVersionEndPoint() {
return new GetVersionEndPoint();
}
I annotated the values from my .properties with #value and then created a method that I instantiated with a bean to to return my server address string.
I then use that string value here in my HttpClientTest class:
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Map;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ConfigurableApplicationContext;
import com.google.gson.Gson;
import com.nulogix.billing.configuration.EndPointTestConfiguration;
import com.nulogix.billing.mockserver.MockServerApp;
#SpringBootTest(classes = EndPointTestConfiguration.class)
public class HttpClientTest {
#Autowired
EndPointTestConfiguration endpoint;
public static final String request_bad = "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|";
public static final String request_good = "ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|-123|-123|-123|0.0|0.0|0.0|0.0|0.0|0.0|0.0";
//gets application context
static ConfigurableApplicationContext context;
//call mock server before class
#BeforeClass
static public void setup(){
SpringApplication springApplication = new SpringApplicationBuilder()
.sources(MockServerApp.class)
.build();
context = springApplication.run();
}
//shutdown mock server after class
#AfterClass
static public void tearDown(){
SpringApplication.exit(context);
}
#Test
public void test_bad() throws ClientProtocolException, IOException {
// missing parameter
String result = Request.Post(endpoint.getAddress())
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(request_bad, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
Map<?, ?> resultJsonObj = new Gson().fromJson(result, Map.class);
// ensure the key exists
assertEquals(resultJsonObj.containsKey("status"), true);
assertEquals(resultJsonObj.containsKey("errorMessage"), true);
// validate values
Boolean status = (Boolean) resultJsonObj.get("status");
assertEquals(status, false);
String errorMessage = (String) resultJsonObj.get("errorMessage");
assertEquals(errorMessage.contains("Payload has incorrect amount of parts"), true);
}
#Test
public void test_good() throws ClientProtocolException, IOException {
String result = Request.Post(endpoint.getAddress())
.connectTimeout(2000)
.socketTimeout(2000)
.bodyString(request_good, ContentType.TEXT_PLAIN)
.execute().returnContent().asString();
Map<?, ?> resultJsonObj = new Gson().fromJson(result, Map.class);
// ensure the key exists
assertEquals(resultJsonObj.containsKey("status"), true);
assertEquals(resultJsonObj.containsKey("errorMessage"), false);
assertEquals(resultJsonObj.containsKey("HasCopay"), true);
assertEquals(resultJsonObj.containsKey("CopayAmount"), true);
assertEquals(resultJsonObj.containsKey("HasCoinsurance"), true);
assertEquals(resultJsonObj.containsKey("CoinsuranceAmount"), true);
assertEquals(resultJsonObj.containsKey("version"), true);
// validate values
Boolean status = (Boolean) resultJsonObj.get("status");
assertEquals(status, true);
String version = (String) resultJsonObj.get("version");
assertEquals(version, "0.97");
}
}
I use it in the request.post, I didn't want to hardcode in my IP address and port number.
When I run the test it says
[ERROR] HttpClientTest.test_bad:63 NullPointer
[ERROR] HttpClientTest.test_good:86 NullPointer
But I am not sure why it is null? I am pretty sure I have everything instantiated and the string is clearly populated..
My package structure for my config is com.billing.mockserver and my package structure for my unit test is com.billing.ws.endpoint.
Here is my application.properties
server.port=9119
server.ssl.enabled=false
logging.config=classpath:logback-spring.xml
logging.file=messages
logging.file.max-size=50MB
logging.level.com.nulogix=DEBUG
billing.engine.address=127.0.0.1
billing.engine.port=9119
billing.engine.api.version=0.97
billing.engine.core.name=Patient_Responsibility
You are missing springboot basic understanding. #Configuration class is to initialize other spring beans and other things and are the first classes which get initialized. You should not #Autowire #configuration class.
In your Configuration class you can either create Spring bean for username and password and autowire that in your test class or directly use #Value in your Test class.
Example: in your configuration class you are creating bean of GetVersionEndPoint and you can autowire that in your Test class.
Update 2:
For test classes, you need to add application.properties file in src\test\resource

NullPointerException in while doing mockito unit test

I am new to mockito Junit testing. This one is my main class which I want to test:
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
#Component
public class IlinqChecksumCalculator {
private static Logger DATA_LOADER_CHECKSUM_CALCULATOR_LOGGER = Logger.getLogger(IlinqChecksumCalculator.class);
public String calculateCheckSum(String rfsdata) throws IOException {
System.out.println(rfsdata);
String checkSumValue = null;
if (StringUtils.isNotBlank(rfsdata)) {
try {
// Create MessageDigest object for MD5
MessageDigest digest = MessageDigest.getInstance("MD5");
// Update input string in message digest
digest.update(rfsdata.getBytes(), 0, rfsdata.getBytes().length);
// Converts message digest value in base 16 (hex)
checkSumValue = new BigInteger(1, digest.digest()).toString(16);
} catch (NoSuchAlgorithmException exception) {
DATA_LOADER_CHECKSUM_CALCULATOR_LOGGER.error(
"Error in determineInputCheckSum() method during calculation of checksum for Input JSON String for ",
exception);
}
}
System.out.println("Final checksum value is:" + checkSumValue);
return checkSumValue;
}
}
This one is my test class:
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class IlinqChecksumCalculatorTest {
private IlinqChecksumCalculator ilinqCheckSum;
#Before
public void setUp() throws Throwable {
MockitoAnnotations.initMocks(this);
}
#Test
public void testCheckSum() throws IOException {
when(ilinqCheckSum.calculateCheckSum("abcde")).thenReturn("defgh");
assertEquals("defgh", ilinqCheckSum.calculateCheckSum("abcde"));
}
}
I am getting a null pointer exception.
Just to answer your question: to handle ilinqCheckSum as mock, you shouuld annotate it with #Mock.
But here you should not use mockito! You want to test IlinqChecksumCalculator and not a mock! You should create a real instance of it and inject the dependendencies as mock if necessary.
By mocking calculateCheckSum method you are not covering any code in your unit test. I think you should not use Mock here. Try below test method.
public void testCheckSum() throws IOException {
String result = ilinqCheckSum.calculateCheckSum("abcde")
assertNotNull(result );
}

How to preview jasper report using java?

i have created a report for my inventory control using IReport.then i found a code
to preview my report,this is that code,
package Report;
import com.mysql.jdbc.Connection;
import java.awt.Container;
import java.sql.Statement;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.swing.JRViewer;
/**
*
* #author Hasindu
*/
public class ReportView extends JFrame
{
public ReportView(String fileName)
{
this(fileName, null);
}
public ReportView(String fileName, HashMap para)
{
super("ABC Solutions Employee/Project Management System (Report Viewer)");
try {
DB dba=new DB();
Connection con=DB.getConnection();
try
{
JasperPrint print = JasperFillManager.fillReport(fileName, para,con);
JRViewer viewer = new JRViewer(print);
Container c = getContentPane();
c.add(viewer);
}
catch (JRException j){
j.printStackTrace();
}
setBounds(10, 10, 900, 700);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
} catch (Exception ex) {
Logger.getLogger(ReportView.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
but my database connection code is returning a statement,this is my database connection code,
package Report;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
public class DB {
public static Statement getConnection()throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/report", "root", "123");
Statement st=con.createStatement();
return st;
}
}
Now i have two problems,
how to edit the report preview code to connect with my database connection code
i tested report preview code by creating this database connection code,
public static Connection getCon()throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/report", "root", "123");
}
but when i run this code it's appears a empty window,
please give a support
if i understand your question correctly ,you are returning a Statement but it require Connection .don't create a statement create a connection to your db and return that connection like following code example.
in reportview class
DB dba=new DB();
Connection con=DB.getCon();
db.class
package Report;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
public class DB {
public static Connection getCon() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/report", "root", "123");
return con;
}
}

Annotations not firing in SharedDriver with cucumber-jvm

This is driving me nuts. I'm running a test framework using cucumber-jvm and trying to get it to take screenshots.
I have looked at the java-webbit-websockets-selenium example that's provided and have implemented the same method of calling my webdriver using the SharedDriver module.
For some reason, my #Before and #After methods are not being called (I've put print statements in there). Can anyone shed any light?
SharedDriver:
package com.connectors;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.Scenario;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.support.events.EventFiringWebDriver;
import java.util.concurrent.TimeUnit;
public class SharedDriver extends EventFiringWebDriver {
private static final WebDriver REAL_DRIVER = new FirefoxDriver();
private static final Thread CLOSE_THREAD = new Thread() {
#Override
public void run() {
REAL_DRIVER.close();
}
};
static {
Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
}
public SharedDriver() {
super(REAL_DRIVER);
REAL_DRIVER.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
REAL_DRIVER.manage().window().setSize(new Dimension(1200,800));
System.err.println("DRIVER");
}
#Override
public void close() {
if(Thread.currentThread() != CLOSE_THREAD) {
throw new UnsupportedOperationException("You shouldn't close this WebDriver. It's shared and will close when the JVM exits.");
}
super.close();
}
#Before()
public void deleteAllCookies() {
manage().deleteAllCookies();
System.err.println("BEFORE");
}
#After
public void embedScreenshot(Scenario scenario) {
System.err.println("AFTER");
try {
byte[] screenshot = getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
} catch (WebDriverException somePlatformsDontSupportScreenshots) {
System.err.println(somePlatformsDontSupportScreenshots.getMessage());
}
}
}
Step file:
package com.tests;
import com.connectors.BrowserDriverHelper;
import com.connectors.SharedDriver;
import com.connectors.FunctionLibrary;
import cucumber.api.Scenario;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.And;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import cucumber.runtime.PendingException;
import org.openqa.selenium.*;
import java.io.File;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.support.events.EventFiringWebDriver;
/**
* Created with IntelliJ IDEA.
* User: stuartalexander
* Date: 23/11/12
* Time: 15:18
* To change this template use File | Settings | File Templates.
*/
public class addComponentsST {
String reportName;
String baseUrl = BrowserDriverHelper.getBaseUrl();
private final WebDriver driver;
public addComponentsST(SharedDriver driver){
this.driver = driver;
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
}
#Given("^I have navigated to the \"([^\"]*)\" of a \"([^\"]*)\"$")
public void I_have_navigated_to_the_of_a(String arg1, String arg2) throws Throwable {
// Express the Regexp above with the code you wish you had
assertEquals(1,2);
throw new PendingException();
}
CukeRunner:
package com.tests;
import org.junit.runner.RunWith;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
#Cucumber.Options(tags = {"#wip"}, format = { "pretty","html:target/cucumber","json:c:/program files (x86)/jenkins/jobs/cucumber tests/workspace/target/cucumber.json" }, features = "src/resources/com/features")
public class RunCukesIT {
}
Put SharedDriver in the same package as RunCukesIT, i.e. com.tests.
When using the JUnit runner, the glue becomes the unit test package (here com.tests), and this is where cucumber-jvm will “scan” the classes for annotations.

Categories

Resources