I'm working on a JavaEE application with EJB and JPA.
I'm doing some tests and entities are persisting. Although, I'd like to remove entities between those tests. I tried to use the method EntityManager.clear() but this doesn't work. When I try to consult one of the old entities, it is still on the EntityManager.
How can I solve this problem?
Invoking EntityManager.clear() will not remove the entities, because they are persisted in the database.
You could close your entity manager factory and open again:
#Before
public void beforeTest() {
entitManagerFactory.close()
entitManagerFactory = // new EntityManagerFactory
}
The problem with this approach is that create an EntityManager may slow down the tests process.
What you could do instead is:
1) You could delete all entities before the test:
#Before
public void beforeTest() {
// execute a query like delete from Person p
}
2) You could use a new ID/values for every test:
#Test
public void test1() {
Person person = PersonTestUtil.createPerson("11111");
}
#Test
public void test2() {
Person person = PersonTestUtil.createPerson("22222");
}
Related
I have a test class to test some functions of JPA repositories, my JPA repositories are connected with H2 db, i want to populate my db with my test entites but i need to do it only once before all tests, this is my test class:
public class EntityRepositoryTest {
#Autowired
EntityJPARepository EntityRepo;
Entity entity;
#Before
public void setup(){
entiti = //initializes entity with values
EntityRepo.save(entiti);
}
//some tests on repo
}
the problem is that #Before annotiation calls it before every test method, and i dont want my entity object to duplicate in H2 db (since save will be called before every method), i also cant do in with annotation #BeforeClass since i need to call save method on #autowired repository. How can i call Setup only once before all tests but stil after repository gets autowired?
You can use the #Before method, you just need a bit of checking to do:
public class EntityRepositoryTest {
#Autowired
EntityJPARepository EntityRepo;
Entity entity;
#Before
public void setup() {
if (entity == null) { // true only for first pass
entity = //initializes entity with values
EntityRepo.save(entity);
}
}
//some tests on repo
}
Alternatively, you can add an #After method that deletes the entity.
you could use the annotation
private static boolean initialized = false;
#BeforeClass
public static void init() {
initialized = true;
}
works the same, just for static initialisations. you should define every initialisation in there. why is that not possibe for you?
you could save in a static flag wether the method has been executed or not.
There is a problem with the #BeforeClass. It is done on a static method because it is run before the instantiation of the test class. That basically means that all #Autowired parameters are not yet set. #BeforeTests method would be appreciated in the cases where you need #Autowired fields to be set but only want to run the method once. But a flag EG instantiated will fix this problem. It is however not very pretty...
I am inserting the data in one method(has #Transactional(propagation = Propagation.Required)) but in the other method(has #Transactional(propagation = Propagation.Required)) if I try to get the same data it is giving null.
Both methods are wrote in service layer with #Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
How to get the data which is inserted in the same transaction.
Something like :-
#Service
public class Service{
#Transactional
public void method(){
mapper.insert(); //insert to DB(Using Mapper interface)
ServiceLayer.method2()
}
}
#Service
public void ServiceLayer{
#Transactional
public static void method2(){
result = mapper.select() //Select inserted data - returning null
}
}
In order to persist the changes made to the current session you can invoke entityManager.flush();
It may be worked, but it's not a solution.
In your case, your Transaction from Service.method() created a transaction that is not committed yet. That's why you can't fetch it.
I found the answer...after removing #transactional from ServiceLayer.method2() it's worked fine.
I am new to JUnit and trying to test a spring web service which uses JPA DAOs. I need to test a service method similar to below.
Service method is annotated with #Transactional(propagation=Propagation.REQUIRED) and ServiceObjectRepository.update() method calls a native sql query to update the db.
#Transactional(propagation=Propagation.REQUIRED)
public void serviceMethod(){
//Read DB for ServiceObject to update
//Call ServiceObjectRepository.update() method to update DB
}
ServiceObjectRepository
public interface ServiceObjectRepository extends JpaRepository<ServiceObject, Integer> {
#Query(value ="UPDATE serviceobjcet AS c SET c.objectstatus= :os WHERE c.objid = :oi", nativeQuery = true)
public Integer update(#Param("os")short objStatus,#Param("oi")int objId);
}
TestClass
#TransactionConfiguration(defaultRollback=true)
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(
locations = "classpath:service-test.xml")
#Transactional
public class ServiceHandlerTest {
#Test
public void testServiceMethod() {
//Create ServiceObject and save to DB
//Call serviceMethod()
//Read DB for updatedServiceObject
assertEquals("Test: Object should be in updated state", new Short(3), updatedServiceObject.getObjectstatus(), 0);
}
}
My test runs and rollback the db transactions. But the problem is when I read the updatedServiceObject after calling the serviceMethod it does not return the updated object. So my test fails with a NullPointerException at the assertEquals. Any idea to overcome this issue?
Finally I came up with a solution, Rather than creating ServiceObject and saving to DB in the test method, I have done it before the test method and deletion of the created objects done after the transaction. So that my test class looks like,
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:service-test.xml")
public class ServiceHandlerTest {
#Before
public void setup() {
//Create ServiceObject and save to DB
}
#Test
public void testServiceMethod() {
//Call serviceMethod()
//Read DB for updatedServiceObject
assertEquals("Test: Object should be in updated state", new Short(3), updatedServiceObject.getObjectstatus(), 0);
}
#After
public void teardown() {
//Delete created ServiceObject from DB
}
}
And I found that test method or test class does not necessary to be transactional in such a case.
I am making Test of My classes so I am inserting so many data for to test my code.
So I am thinking to make some mechanism of savepoint and rollback in DB.
I am using postgresql as DB sever.
Following is my code for test :
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration("file:src/main/webapp/WEB-INF/ls-dispatcher-servlet.xml")
public class AddBindingProcessorTest extends IntegrationTestBase {
#Autowired
private AddBindingProcessor processor;
public AddBindingProcessorTest(){
}
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void add() throws Exception {
AddBinding command;
command = new AddBinding();
command.setId(50l);
command.setBindingName("bindingtest1");
command.setBindingPrice((double)253);
BindingTypeResponse response = (BindingTypeResponse)processRequest(command);
System.out.println("from addbindingprocessor test "+response.getBindingName());
}
}
Here I am setting value through command object and passing to ProcessRequest() Method that will store data inside DB using hibernate.
Still I have to write assert in my testProcess() method that will check data is correct or not ?
So my question is that I when this transaction starts in setUp() method one savepoint should be created and then testProcess() method will be executed and assert check for the data that they are correct or not and then in tearDown() method I want to rollback to savepoint that is set in setUp() method.
So how to do so ? If Anyone can just guide me that what I ll have use and how to move forward then I ll learn that thing and go by myself.
I just want guidance about it that what I ll have to use and where ?
Thank You All.
If I get you right, you can just use the
#TransactionConfiguration(defaultRollback = true)
annotation below your #ContextConfiguration annotation.
This will rollback the changes in your tests after every run.
user3145373 pointed out, that the attribute transactionManager="context bean transaction manager" in #TransactionConfiguration needed to be set also.
It is part of the spring-test lib.
I am new to automated testing and dbUnit. So I would appreciate your advice.
I am going to create a test suite, that will run the following way:
create an in-memory H2 database
run DDL scripts to create tables
run dbUnit to insert initial data (let's call it STATE0) that will be used by all tests.
run tests
Till there it looks nice for me, but what I don't understand, is how do I revert the database to the STATE0 after a test run and changed the data?
Can I do it with dbUnit?
Or with something else?
Should I recreate the database before each test?
Simple not commiting transactions in tests is not appropriate for me, because the tests will eventually run more than one transaction over may be more than one database connection.
DBUnit can do the work four you automatically if you write your #BeforeClass, #Before and #After methods properly. E.g. in our project, using Derby, one such test case looks like
public class MyTest {
protected static IDataSet getDataSet() throws Exception {
URL url = MyTest.class.getClassLoader().getResource("MyDataSet.xml");
return new XmlDataSet(new FileInputStream(url.getPath()));
}
private static JdbcDatabaseTester databaseTester;
#BeforeClass
public static void setUpClass() throws Exception {
// Init test environment, session etc.
databaseTester = new JdbcDatabaseTester(
"org.apache.derby.jdbc.ClientDriver",
"jdbc:derby://localhost:1527/myschema",
"username", "password");
databaseTester.setDataSet(getDataSet());
}
#AfterClass
public static void tearDownClass() {
// Close session etc.
}
#Before
public void setUp() throws Exception {
databaseTester.onSetup();
}
#After
public void tearDown() throws Exception {
databaseTester.onTearDown();
}
#Test
public void test() throws Exception { ... }
}
This code puts back (a subset of) the DB schema to the state defined by MyDataSet.xml after each test. (Note that, as #Pascal commented, the reset may not always be full - if a test modifies a table which is not in the dataset, it won't be affected by the #Before / #After methods.)
To initialize the database to the initial dataset, just implement these methods in your test case :
#Override
protected DatabaseOperation getSetUpOperation() throws Exception
{
return DatabaseOperation.CLEAN_INSERT; // by default (will do DELETE_ALL + INSERT)
}
#Override
protected DatabaseOperation getTearDownOperation() throws Exception
{
return DatabaseOperation.NONE; // by default
}
You may have foreign keys constraints if some of your tests insert rows in an empty table (not defined in initial dataset for example).
Just add this empty table in your dataset without any row :
<mydb_mypopulatedtable id="1" name="toto" alias="funky"/>
<mydb_mypopulatedtable id="2" name="titi" alias="groovy"/>
<mydb_mypopulatedtable id="3" name="tutu" alias="creepy"/>
<mydb_myemptytable />
Here, myemptytable has a foreign key to mypopulatedtable. If myemptytable was not defined, DBUnit would try to delete the mypopulatedtable but will fail because of the constraint. If defined, DBUnit will delete myemptytable rows before.