in BeforeClass method how to insert init data to db - spring-test

I have a UserServiceTest, I want to init load some user data to database for tests e.g. queryByName, groupByAge and so on . And I want to only load once in this class, so I want to use BeforeClass
#BeforeClass
public static void init(){
// ...
}
but in this case I find I cannot use jdbcTemplate to insert data just like in Before e.g.
#Before
public void setUp(){
// prepare test data first
jdbcTemplate.execute("insert into user(firstname,lastname,birthday) values(...);");
}
So in BeforeClass method how to insert init data?

Alternatively you can use TestExecutionListeners in order to initialise your database before test class.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = TestConfig.class)
#TestExecutionListeners(mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS, listeners = {
DbInitializerTestListener.class })
public class DbTest {
}
public class DbInitializerTestListener extends AbstractTestExecutionListener {
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
public void beforeTestClass(TestContext testContext) throws Exception {
testContext.getApplicationContext()
.getAutowireCapableBeanFactory()
.autowireBean(this);
jdbcTemplate.execute("insert into user(firstname,lastname,birthday) values(...);");
}
}
Or you may consider DbUnit framework.

Related

How to use the mock object of the test class and call main method from the test class

In the test class trying to test the main method and not sure how to use the mock object here.
How to use the mock object orders to call the main method and it's methods inside the main method
Any suggestions on how this can be done?
public class Orders {
public static void main(String[] s) {
Orders jp = new Orders();
jp.method1();
List<OrderItems> lstOrdItms = jp.getListOrderItems();
jp.processOrderItems( lstOrdItms );
}
public void method1(List<OrderItem> lstOrderItem) {
.........
}
public List<OrderItem> getListOrderItems() {
............
}
public void processOrderItems() {
............
}
}
public class OrdersTest {
#Mocks
Orders orders;
.....
#Before
public void setUp() {
........
}
#Test
public void testMain() throws SQLException {
// Not sure how to test here
// This will actually execute the main method instead of mock.
orders.main(new String[]{});
}
}

JUnit, Threads and Transactions

I have a test calling a transactional method on a separate thread like so:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:application-context.xml")
public class Test {
#Autowired
DatabaseBatchService databaseBatchService;
#Test
#Transactional
public void testConcurrentSaves() {
Entity e = Entity.createNew();
databaseBatchService.insert(e);
// Check database for inserted entities
}
}
#Component
class DatabaseBatchService implements Runnable {
#PostConstruct
public void init() {
Executors.newSingleThreadScheculedExecutor()
.scheduleAtFixedRate(this, 0, 100, TimeUnit.MILLISECONDS);
}
public synchronized void submit(Entity e) {
// cache entity
}
#Transactional
private synchronized void save() {
// insert cached entities
}
#Override
public void run() {
this.save();
}
}
As the entity is inserted, using logging I can see it appearing in the database. However when I check the state of the database at the end of the test method, the database is empty.
I understand that this is due to the transaction for the thread being rolled back.
From the test, how can I commit these transactions so that the inserted data is available for the test method to see?

Mockito - Testing method that calls private methods

I was trying to find solution but haven't found yet. I tried to test public method which has calls of the couple of private ones inside. One of the problem that private method retrieves Hibernate's Criteria by generic method that in its turn retrieves it through chain of another generic methods. Please take a look at the code below. Frankly I'm not sure that it is possible to test that case but if anyone has ideas please suggest them:
ConcreteDao
public class ConcreteDao extends EntityDao<ConcreteEntity> {
public Class<ConcreteEntity> getClassType() {
return ConcreteEntity.class;
}
}
EntityDao
public abstract class EntityDao<T> extends AbstractDao<T>{
public List<T> getEntityByFilter(EntityFilter filter) {
Criteria criteria = getCriteriaByFilter(filter.getFilters());
criteria.setMaxResult(filter.getMaxResult());
criteria.setFirstResult(filter.getFirstResult());
criteria.addOrder(Order.asc(filter.getSortedField()));
criteria.list();
}
private Criteria getCriteriaByFilter(List<CustFilter> filters) {
Criteria criteria = getCriteria();
for (CustFilter filter : filters) {
filter.addrestrictionToCriteria(criteria, filter.getProperty(), filter.getValue());
}
return criteria;
}
}
AbstractDao
public abstract class AbstractDao<T> {
private EntityManagerFactory entityManagerFactory;
public abstract getClassType();
public Criteria getCriteria() {
return getSession().createCriteria(getClassType());
}
public Session getSession() {
Session session = (Session) getEntityManager().getDelegate();
return session;
}
public EntityManager getEntityManager() {
entityManagerFactory.getEntityManager();
}
}
Test class
#RunWith(MockitoJUnitRunner.class)
public class ConcreteDaoTest {
#Mock
private EntityManager entityManager;
#Mock
private Session session;
#Mock
private Criteria criteria;
private List<CustFilter> filters;
private EntityFilter entityFilter;
private List<ConcreteEntity> resultList;
#InjectMocks
private ConcreteDao concreteDao = new ConcreteDao;
public void init() {
filters = new ArrayLis<CustFilter>();
CustFilter custFilter = new CustFilter();
//fill filter;
filters.add(custFilter);
entityFilter = new EntityFilter();
//fill entityFilter
entityFilter.setFilters(filters);
ConcreteEntity concreteEntity = new ConcreteEntity();
resultList = new ArrayList<ConcreteEntity>();
resultList.add(concreteEntity);
}
#Test
public void getEntityByFilterTest() {
when(concreteDao.getEntityManager).thenReturn(entityManager);
when(concreteDao.getSession()).thenReturn(session);
when(concretedao.getCriteria()).thenReturn(criteria);
when(filter.getFilters()).thenReturn(filters);
when(filter.getMaxResult()).thenReturn(10);
when(filter.getFirstResult()).thenReturn(0);
when(filter.getSortedField()).thenReturn("firstName");
when(criteria.list()).thenReturn(resultList);
List<ConcreteEntity> result = concreteDao.getEntityByFilter(entityFilter);
Assert.assertThen(result. is(notNullValue()));
}
}
With Mockito, you cannot mock private method calls.
Try PowerMockito with which you can mock any kinds of methods like static methods, private methods, local method instantiations and so on.

Unable to get SchemaAction.CREATE to work

My Spring Data Cassandra configuration looks like this:
#Configuration
#EnableCassandraRepositories(basePackages = {
"mypackage.repository.cassandra",
})
public class DistributedRepositoryConfiguration {
// ...
#Bean
public CassandraSessionFactoryBean session() throws Exception {
CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
session.setCluster(cluster().getObject());
session.setKeyspaceName(configuration.get().getKeyspace());
session.setConverter(converter());
session.setSchemaAction(SchemaAction.CREATE);
return session;
}
}
Generally, Spring Data Cassandra works in my project. However, when I start my application I have no tables created. Anyone who could tell me what I'm doing wrong?
It is not written well in documentation if you want to have automatic table creation you should tell cassandra where to look for entity classes:
<cassandra:mapping entity-base-packages="your.package" />
If you want to do the same using annotiation configuration you have to explicitly tell CassandraTemplate where to look for it. So
#Bean
public CassandraSessionFactoryBean session() throws Exception {
CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
session.setCluster(cluster().getObject());
session.setKeyspaceName(keyspaceName);
session.setConverter(converter());
session.setSchemaAction(SchemaAction.CREATE);
return session;
}
#Bean
public CassandraConverter converter() throws Exception {
return new MappingCassandraConverter(mappingContext());
}
#Bean
public CassandraMappingContext mappingContext() throws Exception {
BasicCassandraMappingContext bean = new BasicCassandraMappingContext();
bean.setInitialEntitySet(CassandraEntityClassScanner.scan(("package.with.your.entities")));
return bean;
}
To do it with ease I suggest using AbstractCassandraConfiguration and override methods which You need.
I checked the class AbstractCassandraConfiguration and found the following code:
public String[] getEntityBasePackages() {
return new String[] { getClass().getPackage().getName() };
}
Since my config class isn't in the main package, the component scan does not find my classes with the #Table annotation. So I override the method "getEntityBasePackages()" using my StartUp class and everything worked fine.
This is my config class:
#Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {
#Value("${spring.data.cassandra.keyspace-name}")
private String keyspaceName;
#Override
protected String getKeyspaceName() {
return keyspaceName;
}
#Override
public String[] getEntityBasePackages() {
return new String[]{AppStartup.class.getPackage().getName()};
}
#Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
return Collections.singletonList(CreateKeyspaceSpecification
.createKeyspace(keyspaceName)
.ifNotExists(true)
.with(KeyspaceOption.DURABLE_WRITES, true)
.withSimpleReplication());
}
#Override
public SchemaAction getSchemaAction() {
return SchemaAction.CREATE_IF_NOT_EXISTS;
}
}
Using this class, your application should create the required keyspace and tables to run.
If you using CassandraDataConfiguration just annotated you base class application with:
#EntityScan("mypackage.repository.cassandra")
The base package information will be used in CassandraDataAutoConfiguration.cassandraMapping method to add this package to cassandra mapping.

JavaFX access ui-elements from Controller(Singleton)

I have a javafx design in the file javafx.fxml where the root element has the following attribute
fx:controller="de.roth.jsona.javafx.ViewManagerFX"
This controller class has a singleton machanism and is binded with some ui-elements.
public class ViewManagerFX {
private static ViewManagerFX instance = new ViewManagerFX();
#FXML
private Slider volumeSlider;
#FXML
private Label volumeLabel;
public IntegerProperty volumeValue = new SimpleIntegerProperty();
#FXML
private TabPane musicTabs;
public List<StringProperty> tabNames = new ArrayList<StringProperty>();
public static ViewManagerFX getInstance() {
return (instance);
}
public void initialize() {
// Volume
volumeSlider.valueProperty().bindBidirectional(volumeValue);
volumeLabel.textProperty().bindBidirectional(volumeValue, new Format() {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo,
FieldPosition pos) {
toAppendTo.append(obj);
toAppendTo.append("%");
return toAppendTo;
}
#Override
public Object parseObject(String source, ParsePosition pos) {
return null; // no need to be implemented
}
});
volumeValue.set(Config.getInstance().VOLUME);
}
public void addMusicFolderTab(final String t, final ArrayList<MusicListItem> items) {
Platform.runLater(new Runnable() {
#Override
public void run() {
Tab m = new Tab("Test Tab");
musicTabs.getTabs().add(0, m);
}
});
}
}
The method addMusicFolderTab is called from a thread that is used to scan files and directories.
In the initialize method I can access the ui-elements but in the method addMusicFolderTab, that is called from the filescanner-thread, the variable musicTabs is null. Here is the exception:
java.lang.NullPointerException
at de.roth.jsona.javafx.ViewManagerFX$3.run(ViewManagerFX.java:110)
I have no clue, why I can't access the TabPane from outside the initialize method.
Aside from the many questionable patterns used here, the problem is that your ViewManagerFX singleton (besides not being a singleton) never has its instance set.
When using FXML, the Controller is created and loaded dynamically by Reflection from the FXMLoader.
What happens is that by calling ViewManagerFX.getInstance(), you access the a different controller than the one created by the FXMLoader. The instance you access is the one created here:
private static ViewManagerFX instance = new ViewManagerFX();
The quickest way to solve the issue is to set the instance in the initialize() since it's called by the FXMLoader on the instance created by the FXMLoader.
public void initialize() {
instance = this;
// Volume
...
}

Resources