Getting frustrated with DBUnit :( Anyone know why I would get dbAssertionFailedError driverClass is null for the below please? dbunitData.xml contains the test data with one row. I know that the connection to the database is fine but the error seems to be triggered by the assertequals.
public class ExtendDBTestCaseTest extends DBTestCase
{
public static final String TABLE_LOGIN = "salarydetails";
private FlatXmlDataSet loadedDataSet;
private SalaryCalculation salaryCalculation;
#SuppressWarnings("deprecation")
protected IDataSet getDataSet() throws Exception
{
loadedDataSet = new FlatXmlDataSet(this.getClass().getClassLoader()
.getResourceAsStream("dbunitData.xml"));
return loadedDataSet;
}
protected void setUp() throws Exception
{
setUpDatabase();
}
#SuppressWarnings("deprecation")
private void setUpDatabase() throws Exception
{
Class.forName("com.mysql.jdbc.Driver");
Connection jdbcConnection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/salary", "someUser", "somePass");
IDatabaseConnection connection = new DatabaseConnection(jdbcConnection);
IDataSet dataSet = getDataSet();
try
{
getSetUpOperation().execute(connection, dataSet);
}
finally
{
connection.close();
}
}
protected DatabaseOperation getSetUpOperation() throws Exception{
return DatabaseOperation.REFRESH;
}
public void testCalculatorNeg() throws Exception
{
salaryCalculation = new SalaryCalculation();
int salary = salaryCalculation.calculator("12345");
assertEquals(0, salary);
}
}
Frustratingly I answered my own question after more trial and error. Just needed to add a teardown method with loadedDataSet.endDataSet(); and now works fine!
Related
I get error :
Wanted but not invoked:
iReimbursementDAO.update(
Reimbursement{id=2, status=Pending, author=User{id=1, username='genericEmployee1', password='genericPassword', f_name null', l_name null', email null', role=Employee}, resolver=null, amount=150.0, description null,creation null, resolution null, receipt null}
);
-> at Test.testProcessPassesWhenUserIsFinanceManagerAndReimbursementExistsAndUpdateSuccessful(ReimbursementServiceTest.java:69)
Actually, there were zero interactions with this mock.
I followed steps from answer to previous post and got my test succeed for a different class. Now I tried the same steps in a second class as shown below and the test fails in one place.
public class ReimbursementServiceTest {
private static IReimursementService reimbursementService;
private static IReimbursementDAO reimbursementDAO;
private Reimbursement REIMBURSEMENT_TO_PROCESS;
private Reimbursement GENERIC_REIMBURSEMENT_1;
private Optional<Reimbursement>
GENERIC_REIMBURSEMENT_2;
private List<Reimbursement> GENERIC_ALL_PENDING_REIMBURSEMENTS;
private User GENERIC_EMPLOYEE_1;
private User GENERIC_FINANCE_MANAGER_1;
#BeforeClass
public static void setUpBeforeClass() throws Exception {
reimbursementDAO = mock(IReimbursementDAO.class);
reimbursementService = new ReimbursementService(reimbursementDAO);
}
#Before
public void setUp() throws Exception {
GENERIC_EMPLOYEE_1 = new User(1, "genericEmployee1", "genericPassword", Role.EMPLOYEE);
GENERIC_FINANCE_MANAGER_1 = new User(1, "genericManager1", "genericPassword", Role.FINANCE_MANAGER);
REIMBURSEMENT_TO_PROCESS = new Reimbursement(2, Status.PENDING, GENERIC_EMPLOYEE_1, null, 150.00);
GENERIC_REIMBURSEMENT_1 = new Reimbursement(1, Status.PENDING, GENERIC_EMPLOYEE_1, null, 100.00);
GENERIC_REIMBURSEMENT_2 = Optional.ofNullable(new Reimbursement(2, Status.APPROVED, GENERIC_EMPLOYEE_1, GENERIC_FINANCE_MANAGER_1, 150.00));
GENERIC_ALL_PENDING_REIMBURSEMENTS = new ArrayList<Reimbursement>();
GENERIC_ALL_PENDING_REIMBURSEMENTS.add(GENERIC_REIMBURSEMENT_1);
}
#Test
public void testProcessPassesWhenUserIsFinanceManagerAndReimbursementExistsAndUpdateSuccessful()
throws Exception{
when(reimbursementDAO.getById(anyInt())).thenReturn(Optional.of(GENERIC_REIMBURSEMENT_1));
when(reimbursementDAO.update(any())).thenReturn(GENERIC_REIMBURSEMENT_2);
assertEquals(GENERIC_REIMBURSEMENT_2,
reimbursementService.process(REIMBURSEMENT_TO_PROCESS, Status.APPROVED,
GENERIC_FINANCE_MANAGER_1));
verify(reimbursementDAO).getById(REIMBURSEMENT_TO_PROCESS.getId());
verify(reimbursementDAO).update(REIMBURSEMENT_TO_PROCESS);
}
#Test
public void testGetReimbursementByStatusPassesWhenReimbursementsAreSuccessfullyReturned() {
when(reimbursementDAO.getByStatus(any())).thenReturn(GENERIC_ALL_PENDING_REIMBURSEMENTS);
assertEquals(GENERIC_ALL_PENDING_REIMBURSEMENTS,
reimbursementService.getReimbursementsByStatus(Status.PENDING));
verify(reimbursementDAO).getByStatus(Status.PENDING);
}
}
public class ReimbursementService implements
IReimursementService {
private final IReimbursementDAO reimbDao;
public ReimbursementService() {
this(new ReimbursementDAO());
}
public ReimbursementService(IReimbursementDAO userDAO2) {
this.reimbDao = userDAO2;
}
#Override
public Optional<Reimbursement> process(Reimbursement
unprocessedReimbursement,
Status finalStatus, User resolver) throws Exception{
if (!resolver.getRole().equals(Role.FINANCE_MANAGER)) {
throw new RegistrationUnsuccessfulException(" be
Finance Manager ");}
if(unprocessedReimbursement.getId()==0)
{ throw new Exception(" reimbursement not found"); }
if(unprocessedReimbursement.getStatus().equals(Status.PENDING))
{
Optional<Reimbursement> reimb=
this.reimbDao.update(unprocessedReimbursement);
if(reimb.isPresent())
{ return reimb; }
else { throw new Exception("unsuccessful update");}
}
return Optional.ofNullable(null);
}
#Override
public List<Reimbursement> getReimbursementsByStatus(Status
status) {
return reimbDao.getByStatus(status);
}
#Override
public Optional<Reimbursement> getById(int id) {
return reimbDao.getById(id);
}
}
You are told what the error is: Wanted but not invoked - You WANTED to have dao.update invoked, but you didn't invoke it. "Actually, there were zero interactions with this mock." exactly, so why are you verifying that the update is called?
Remove this from the test verify(reimbursementDAO).update(REIMBURSEMENT_TO_PROCESS);
I'm new in unit test, and I'm trying to write some tests for my DAO's. I have followed some tutorials/answers here, but most of them don't apply to my DAO's.
I get this warning when I run the test
org.mockito.exceptions.verification.WantedButNotInvoked:
Wanted but not invoked:
mockConn.prepareStatement();
What is wrong?
private ApprovalConditionDAO approvalConditionDAO;
#Mock
DataSource mockDataSource;
#Mock
Connection mockConn;
#Mock
PreparedStatement mockPreparedStmnt;
#Mock
CallableStatement cs;
#Mock
ResultSet mockResultSet;
#Before
public void setUp() throws SQLException {
approvalConditionDAO = new ApprovalConditionDAO();
when(mockDataSource.getConnection()).thenReturn(mockConn);
when(mockDataSource.getConnection(anyString(),
anyString())).thenReturn(mockConn);
when(mockConn.prepareStatement(anyString(),
anyInt())).thenReturn(mockPreparedStmnt);
doNothing().when(mockConn).commit();
doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);
}
#Test
public void testCreateWithNoExceptions() throws SQLException {
ArrayList<ApprovalConditionBean> actualValues = approvalConditionDAO.getAllApprovalCondition();
//verify and assert
verify(mockConn, times(1)).prepareStatement(anyString());
verify(mockPreparedStmnt, times(1)).execute();
verify(mockConn, times(1)).commit();
verify(mockResultSet, times(2)).next();
verify(mockResultSet, times(1)).getString("ID");
verify(mockResultSet, times(1)).getString("EIT_CODE");
verify(mockResultSet, times(1)).getString("FRIST_KEY_TYPE");
verify(mockResultSet, times(1)).getString("FRIST_KEY_VALUE");
verify(mockResultSet, times(1)).getString("FRIST_EIT_SEGMENT");
verify(mockResultSet, times(1)).getString("OPERATION");
verify(mockResultSet, times(1)).getString("SECOND_KEY_TYPE");
verify(mockResultSet, times(1)).getString("SECOND_KEY_VALUE");
verify(mockResultSet, times(1)).getString("SECOND_EIT_SEGMENT");
verify(mockResultSet, times(1)).getString("APPROVAL_CODE");
}
And this is the Dao that I want to test it.
public class ApprovalConditionDAO extends AppsproConnection {
Connection connection;
PreparedStatement ps;
CallableStatement cs;
ResultSet rs;
RestHelper rh = new RestHelper();
public ArrayList<ApprovalConditionBean> getAllApprovalCondition() {
ArrayList<ApprovalConditionBean> approvalConditionList =
new ArrayList<ApprovalConditionBean>();
try {
connection = AppsproConnection.getConnection();
String query =
"SELECT * FROM "+" "+getSchema_Name()+".XXX_APPROVAL_CONDITION";
ps = connection.prepareStatement(query);
rs = ps.executeQuery();
while (rs.next()) {
ApprovalConditionBean approvalConditionBean = new ApprovalConditionBean();
approvalConditionBean.setId(rs.getString("ID"));
approvalConditionBean.setEitCode(rs.getString("EIT_CODE"));
approvalConditionBean.setFirstKeyType(rs.getString("FRIST_KEY_TYPE"));
approvalConditionBean.setFirstKeyValue(rs.getString("FRIST_KEY_VALUE"));
approvalConditionBean.setFirstEitSegment(rs.getString("FRIST_EIT_SEGMENT"));
approvalConditionBean.setOperation(rs.getString("OPERATION"));
approvalConditionBean.setSecondKeyType(rs.getString("SECOND_KEY_TYPE"));
approvalConditionBean.setSecondKeyValue(rs.getString("SECOND_KEY_VALUE"));
approvalConditionBean.setSecondEitSegment(rs.getString("SECOND_EIT_SEGMENT"));
approvalConditionBean.setApprovalCode(rs.getString("APPROVAL_CODE"));
approvalConditionList.add(approvalConditionBean);
}
} catch (Exception e) {
//("Error: ");
e.printStackTrace();
} finally {
closeResources(connection, ps, rs);
}
return approvalConditionList;
}
And this as my AppsproConnection Calss
public static Connection getConnection(boolean commit) {
if (CommonConfigReader.getValue("CONNECTION_TYPE").equalsIgnoreCase("JDBC")) {
return getJDBCConnection(commit);
} else {
return getDSConnection(commit);
}
}
public static Connection getConnection() {
if (CommonConfigReader.getValue("CONNECTION_TYPE").equalsIgnoreCase("JDBC")) {
return getJDBCConnection();
} else {
return getDSConnection();
}
}
You didn't call the method you wanted to test from the test method.
You don't event have a test object to do so.
class TestClass {
private MyDao underTest;
#Before
public void setUp() throws SQLException {
underTest = new MyDao();
// mocking things...
}
}
And using this test object you have to call the method you actually want to test from a test method.
#Test
public void testCreateWithNoExceptions() throws SQLException {
// ...
ArrayList<ApprovalConditionBean> actualValues = underTest.getAllApprovalCondition();
// assertions
}
If you cannot manipulate how you get the connection from a static class then you can refactor your method to get a connection from another method in the same class.
public ArrayList<ApprovalConditionBean> getAllApprovalCondition() {
// ...
connection = getConnection();
// ...
}
Connection getConnection() {
return AppsproConnection.getConnection();
}
If you are using like this you can instantiate the test object in a way that you can manage what kind of Connection is returned for tests.
#Before
public void setUp() throws SQLException {
when(mockConn.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStmnt);
doNothing().when(mockConn).commit();
doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);
underTest = new MyDao(){
#Override
public Connection getConnection() {
return mockConn;
}
};
}
We are returning the mocked connection from getConnection. This method is called from the getAllApprovalCondition method. In production it is still providing connection through AppsproConnection.
Trying Mock method that have KeyHolder. But keyHolder is null. Method is working. Please help. Need to modify test some how.
#Autowired
private KeyHolderFactory factory;
#Override
public Integer createRss(String url) throws Exception {
KeyHolder holder = factory.newKeyHolder();
try {
jdbcTemplate.update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(CREATE_RSS, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, url);
return ps;
}
}, holder);
} catch (DataAccessException e) {
throw new Exception("Rss already exist");
}
return holder.getKey().intValue();
}
This is my test body.Trying to mock keyHolder but it does not work.
public class RSSDaoImplTest {
#InjectMocks
private RSSDaoImpl target;
#Mock
private KeyHolder keyHolder;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
this.mockDS = Mockito.mock(DataSource.class);
this.mockJT = Mockito.mock(JdbcTemplate.class);
target = new RSSDaoImpl();
target.setJdbcTemplate(mockDS);
target.setJdbcTemplate(mockJT);
}
#Test
public void testCreateRss() throws Exception {
Mockito.when(mockJT.update(Mockito.any(PreparedStatementCreator.class), Mockito.any(KeyHolder.class)))
.thenReturn(1);
Mockito.doReturn(1).when(keyHolder).getKey().intValue();
int actual = target.createRss("test");
assertEquals(1, actual);
}
}
Could not find any solution on stackoverflow. Thank you in advance
You can try the following code:
Mockito.when(keyHolderFactoryMock.newKeyHolder()).thenReturn(keyHolderMock);
Mockito.when(keyHolderMock.getKey()).thenReturn(1);
Mockito.when(jdbcTemplate.update(Mockito.any(PreparedStatementCreator.class), Mockito.any(KeyHolder.class))).thenReturn(1);
I have this class (my database connection factory):
#ApplicationScoped
public class ConnectionFactory {
private ComboPooledDataSource datasource;
private Long open = 0l;
private Long close = 0l;
#PostConstruct
public void init() throws PropertyVetoException, SQLException {
datasource = new ComboPooledDataSource();
datasource.setDriverClass("org.postgresql.Driver");
datasource.setJdbcUrl("jdbc:postgresql:dbcampanha");
datasource.setUser("postgres");
datasource.setPassword("admin");
datasource.setMinPoolSize(1);
datasource.setMaxPoolSize(5);
datasource.setCheckoutTimeout(30000);
datasource.setUnreturnedConnectionTimeout(30);
datasource.setMaxIdleTime(30);
datasource.setDebugUnreturnedConnectionStackTraces(true);
datasource.setAcquireIncrement(1);
}
#Produces
#RequestScoped
public Connection getConnection() throws ClassNotFoundException {
open++;
try {
Connection connection = datasource.getConnection();
connection.setAutoCommit(false);
return connection;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void close(#Disposes Connection connection) {
close++;
try {
connection.commit();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Long getOpenedConnectionCounter() {
return open;
}
public Long getClosedConnectionCounter(){
return close;
}
public ComboPooledDataSource getDatasource(){
return datasource;
}
}
I use this class with an JAX-RS application. And for some tests using this route:
#RequestScoped
#Path("/test")
public class TesteService {
#Inject
private Connection connection;
#GET
#Produces(MyMediaType.JSON)
#Path("/yes")
public Response success() throws SQLException {
connection.getClientInfo("");
return Response.ok().build();
}
}
And this class for my Client:
public class TesteMain {
private static final String prefix = "http://localhost:8080/schoolwork/service/test/";
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10000; i++) {
Request request = new Request(prefix + "yes");
request.start();
if(i % 10 == 0)
Thread.sleep(1000l);
}
}
public static class Request extends Thread {
private String rota;
public Request(String rota){
this.rota = rota;
}
#Override
public void run() {
try {
HttpURLConnection url = (HttpURLConnection) (new URL(rota).openConnection());
url.connect();
System.out.println(url.getResponseCode() == 200 ? "SUCCESS" : "ERROR");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I receive this infos:
{
"opened-connection": 789,
"closed-connection": 867,
}
Yes, I have a number of closed database connection greater than opened. HOW? Any idea for this?
I use
Tomcat 7 + Java 7
P.S. I am sorry for my bad English :/
SOLVED
I change my counters for AtomicInteger objects, and works perfectly.
So, two quick comments:
Your counters are (boxed) longs read and updated willy-nilly by 1000 concurrent Threads. Their values will in general be unpredictable and nondeterministic. They certainly won't accurately count what you intend them to count. Consider using atomic operations on AtomicLongs instead.
Your commit() (or rollback()) should be attached to your database business logic, the part where you can tell a unit of work has either succeeded or failed. You shouldn't automatically commit on close.
This class is the only thing that should ever access the database and I'd like to give it a single connection object when my application starts up. However, instantiation may cause an exception to be thrown, so I can't do this:
public class DBManager {
private static Connection conn = Database.getReadOnlyConnection();
...
...
}
I have a pretty ugly workaround, and I was wondering if there's a better way.
public class DBManager {
private static Connection conn = null;
private static DBManager instance = null;
public static DBManager getInstance() throws SQLException, ClassNotFoundException {
if (instance == null){
instance = new DBManager();
}
return instance;
}
private DBManager() throws SQLException, ClassNotFoundException {
conn = Database.getReadOnlyConnection();
}
...
...
}
There's also this alternative:
public class DBManager {
private static Connection conn = null;
public static void setConnection(Connection conn) throws NotSupportedException{
if (conn == null){
this.conn = conn;
}
else {
throw new NotSupportedException();
}
}
...
...
}
Is there a nicer way of handling this in Java?
Update
I've decided to use a static initializer block.
public class DBManager {
private static Connection conn;
static {
try {
conn = getReadOnlyConnection();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
...
...
}
This causes the application to fail early if the database cannot be reached and avoids the problem of having to ensure that the DBManager is only being used via an instance.
You program should be more robust - sure you may have a connection now, but what happens if the DB does down - use the same logic for no DB now as DB goes down later
How about a static method and checking if the connection is still valid,
public class Config{
private static Connection con;
private String dbUrl = "jdbc:mysql:/localhost:3306/dbname","username","password";
public static Connection getConnection() throws SQLException{
if(con== null){
con = DriverManager.getConnection(dbUrl);
}
if(!con.isValid(10)){
con = DriverManager.getConnection.getConnection(dbUrl);
}
return con;
}
}