I want to test pushing and pulling data from a database. Will this pattern work?
Specifically, will using this pattern successfully push and pull from the database and will it clean up afterwards?
private Connection connection;
private Savepoint savepoint;
#Before
public void setUp() throws Exception {
connection = MyConnectionGenerator();
connection.setAutoCommit(false);
savepoint = connection.setSavepoint();
}
#Test
public void myTest() throws Exception{
//use the connection for CRUD ops testing
}
#After
public void tearDown() throws Exception {
connection.rollback(savepoint);
connection.close();
}
Related
I am working with Spring Boot and Dart. When I hit the URL (using POSTMEN/Browser) to insert some data in MySql I got the response correctly. But WHen I send the 3 requests consecutively from Flutter Front-end using Dart language it most of the time returned the result of 2 GET request and through the error for the 3rd request and most of the time it works for all request.
Following is the connection service that I am using on backend to store the data.
ConnectionService.java
#Service
public class ConnectionService {
private static final Logger log = LoggerFactory.getLogger(ConnectionService.class);
Connection connection = null;
#Value("${spring.datasource.url}")
String datasourceUrl = "jdbc:mysql://localhost/databaseName?autoReconnect=true&useSSL=false";
public Connection createConnection() throws SQLException {
connection = DriverManager.getConnection(datasourceUrl, "root", "root");
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
return connection;
}
public void closeConnection() {
try {
connection.close();
} catch (Exception e) {
log.error(e.toString());
}
}
}
I am creating the object of the Connection service class and call the createConnection() to create the connection and closeConnection() to close that one.
Controller.java
#RestController
#RequestMapping("/user")
public class UserController {
#Autowired
ConnectionService connectionService;
#GetMapping(path = "/test")
public void testFunction(#RequestParam(name = "abc") String abc) throws SQLException
{
Connection connection = connectionService.createConnection();
if (abc.isExist(param1,param2,connection))
{
//some code
connectionService.closeConnection();
} else
{
//some operation
connectionService.closeConnection();
}
}
Guide me to resolve this issue.
Thanks
They problem is that instead of closing the instance connection that I have created locally I am closing the main connectionService instance. This is the problem.
Now connectionService.closeConnection();
It should be connection.closeConnection();
I'm trying to create a database connection library to be used in all my apps. I want to make sure that this library is fully unit tested and so i'm trying to use dependency injection.
I have this class which i want to ensure is tested:
public class ConnectionFactory {
private String dataSourceName;
public ConnectionFactory(String dataSourceName) {
if(dataSourceName == null) {
throw new NullPointerException("dataSourceName can't be null");
}
this.dataSourceName = dataSourceName;
}
public Connection getConnection() throws SQLException {
Connection connection = getDataSource(dataSourceName).getConnection();
if(connection != null) {
return connection;
}
...
}
// Get a datasource object
private DataSource getDataSource(String dataSourceName) {
...
try {
Context ctx = new InitialContext();
dataSource = (DataSource) ctx.lookup("java:comp/env/" + dataSourceName);
} catch (NamingException e) {
...
}
return dataSource;
}
}
I want to be able to simply call this class from all my apps with something as simple as this:
public class MyApp {
public static void main(string[] args) {
ConnectionFactory connectionFactory = new ConnectionFactory("jdbc/myDataSource");
Connection connection = connectionFactory.getConnection();
}
}
I've started writing unit tests for this ConnectionFactory, but quickly realized that with my current code I can't mock the DataSource object so it's trying to actually connect to a real data source.
#RunWith(Nested.class)
public class ConnectionFactoryTest {
public class Constructor {
#Test
public void shouldThrowNullPointerIfParamIsNull() {
assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> { new ConnectionFactory(null); })
.withMessage("dataSourceName can't be null");
}
}
public class GetConnection {
public class WithDataSourceAvailable {
#Test
public void shouldErrorIfParamIsNull() {
ConnectionFactory connectionFactory = new ConnectionFactory("jdbc/myDataSource"); // <-- This is going to fail b/c it's trying to actually fetch a real data source
}
}
}
}
How can I properly use Dependency Injection so that I can write unit tests that don't actually try to connect to a data source?
Take a look at Mockito I find it easy to use for this type of mocking.
I have a class that needs to be unit tested:
public class AMQProducer {
private final String TCP = "tcp://";
private final String COLON = ":";
AMQProducer() {
}
public AMQProducer(String ip, long port) throws JMSException {
try {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(TCP + ip + COLON + port);
Connection connection = connectionFactory.createConnection();
} catch (JMSException e) {
throw e;
}
}
}
I have a test case:
#RunWith(PowerMockRunner.class)
#PrepareForTest()
public class TestAMQProducer {
#Mock
Connection connection;
#Mock
ActiveMQConnectionFactory connectionFactory;
#Test
public void test() throws Exception {
PowerMockito.whenNew(ActiveMQConnectionFactory.class).withAnyArguments().thenReturn(connectionFactory);
PowerMockito.when(connectionFactory.createConnection()).thenReturn(connection);
AMQProducer producer = new AMQProducer("random", 1234);
}
}
When I run the test case, the mock object of ActiveMQConnectionFactory isn't being used. Instead, the actual implementation is being used and there's a TCP connection being made:
javax.jms.JMSException: Could not connect to broker URL: tcp://random:2333. Reason: java.net.UnknownHostException: random
I tried with Powermockito and Mockito, but failed with both. How do I mock the objects and how do I successfully run the test case?
I am new to unit testing and tried to get help from various communities, but didn't find the appropriate answer. Any help would be appreciated. Thanks!
You cannot test it with the current structure of your code - you create new ActiveMQConnectionFactory in your constructor. Use dependency injection instead.
With Mockito:
public class AMQProducer {
AMQProducer() {}
public AMQProducer(ActiveMQConnectionFactory connectionFactory) throws JMSException {
Connection connection = connectionFactory.createConnection();
}
}
public class TestAMQProducer {
private final Connection connection = mock(Connection.class);
private final ActiveMQConnectionFactory connectionFactory = mock(ActiveMQConnectionFactory.class);
#Test
public void test() throws Exception {
doReturn(connection).when(connectionFactory).createConnection();
// actual test here
}
}
I am trying to create tests for my app which connects to a database. The DataSource is a conection pool (Hikari).
Here is my test configuration:
#Configuration
public class SqlTestConfig {
#Bean
DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(2);
config.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
config.setJdbcUrl("jdbc:sqlserver://serversql:1433;database=myDatabase");
config.setUsername("user");
config.setPassword("password");
return new HikariDataSource(config);
}
}
Here is my test class:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = SqlTestConfig.class)
#Slf4j
#Sql(
scripts = "/clearTables.sql",
config = #SqlConfig(separator = "GO")
)
public class SqlTest {
#Autowired
DataSource dataSource;
#Test
public void test1() throws SQLException {
log.info("catalog:" + dataSource.getConnection().getCatalog());
}
#Test
public void test2() throws SQLException {
log.info("catalog:" + dataSource.getConnection().getCatalog());
}
#Test
public void test3() throws SQLException {
log.info("catalog:" + dataSource.getConnection().getCatalog());
}
#Test
public void test4() throws SQLException {
log.info("catalog:" + dataSource.getConnection().getCatalog());
}
}
Notice that the MaximumPoolSize is set to 2. When I run the test class the first two tests are successfully completed and the remaining tests fail because the pool gets depleted of connections (connection timeout).
I believe the problem is because of the #Sql annotation which causes DataSourceInitializer -s to be created to execute the cleanup script but the connections are never returned to the pool.
When I set MaximumPoolSize to 4 all tests are successfully completed. I cannot tell if I have made a configuration error or if this is a bug in Spring.
The getConnection acquires connection from underlying pool. Change your tests to properly close the acquired connection like so:
#Test
public void test1() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
log.info("catalog:" + connection.getCatalog());
}
}
I am trying to unit test a thin data access layer that I've written. I was hoping I wouldn't have to inject a stub of DriverManager into the class that makes the connection, and I don't have a mock framework available. I have check my implementation against MockRunner's MockDriver and it is very similar, but when I run the test I get a SQLException: "No suitable driver found for jdbc:mysql://localhost:3306." Here is the stub code:
public class DriverStub implements Driver
{
#Override
public boolean acceptsURL(String URL) throws SQLException
{
return true;
}
#Override
public Connection connect(String url, Properties info) throws SQLException
{
return new ConnectionStub();
}
#Override
public int getMajorVersion()
{
return 1;
}
#Override
public int getMinorVersion()
{
return 0;
}
#Override
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
throws SQLException
{
return new DriverPropertyInfo[0];
}
#Override
public boolean jdbcCompliant()
{
return true;
}
}
A fragment of the calling code:
Connection connection = null;
try
{
Class.forName(driver).newInstance();
}
...
try
{
connection = Drivermanager.getConnection(...);
}
...
The Driver implementation should register an instance of the Driver through DriverManager.registerDriver in its static initialiser.
public class DriverStub implements Driver {
static {
java.sql.DriverManager.registerDriver(new DriverStub());
}
...
}
It's a complete and utter hack, but there you go. Personally, I'd suggest ignoring DriverManager and linking directly to the driver.
This seems to be far more effort than it's worth. Why would you want to stub the DriverManager? What does that test? How do you prove the worth of your data access layer by not using a real driver manager? Don't you want to connect to a database to test?
I'd load the JDBC driver and be done with it. This seems like mocking run amok to me.