cancel
Showing results for 
Search instead for 
Did you mean: 

Unit test does not load test data

kaihuener
Champ in-the-making
Champ in-the-making
Hey all,

I want to write a simple unit test in a standard maven directory structure. An activiti.cfg.xml file is located in src/main/resources with all relevant configuration (database, ldap, mail, etc). For the unit test, I want to replace several configuration, e.g. H2 in-memory as database.

I also want to "bypass" LDAP authentification by (temporarily) adding a test user to the in-memory database. For that, I want to use the approach which the activiti team uses to add demo data, i.e. a spring bean that adds users to the (running) process engine by the identity service.

To achieve this, I added a simple activiti.cfg.xml to src/test/resources:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
         
   <bean id="testDataGenerator" class="cdq.cdl.processes.TestDataGenerator"
      init-method="init">
      <property name="processEngine" ref="processEngine" />
   </bean>
   
   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
      <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
   </bean>
   
   <bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
   </bean>

   <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
      <property name="dataSource" ref="dataSource" />
      <property name="transactionManager" ref="transactionManager" />
      <property name="databaseSchemaUpdate" value="true" />
   </bean>

   <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean"
      destroy-method="destroy">
      <property name="processEngineConfiguration" ref="processEngineConfiguration" />
   </bean>
</beans>


The only "special" thing is the testDataGenerator bean:
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.identity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestDataGenerator {

   protected static final Logger LOGGER = LoggerFactory.getLogger(TestDataGenerator.class);

   protected transient ProcessEngine processEngine;
   protected transient IdentityService identityService;

   public void init() {
      this.identityService = processEngine.getIdentityService();

      LOGGER.info("Initializing test users");
      initDemoUsers();
   }

   public void setProcessEngine(ProcessEngine processEngine) {
      this.processEngine = processEngine;
   }

   protected void initDemoUsers() {
      createUser("foo", "bar");
   }

   protected void createUser(String userId, String password) {

      if (identityService.createUserQuery().userId(userId).count() == 0) {

         User user = identityService.newUser(userId);
         user.setPassword(password);
         identityService.saveUser(user);
      }
   }
}


Finally, I have a simple test case:
import static org.junit.Assert.assertTrue;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
import org.junit.Test;

public class TestBasic {
   
   @Rule
   public ActivitiRule activitiRule = new ActivitiRule();

   @Test
   public void testLogin() {
      boolean check = activitiRule.getIdentityService().checkPassword("foo", "bar");
      assertTrue(check);
   }
}


When I run the test, I get the following output:
2013-12-14 11:33:48 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
Information: Loading XML bean definitions from class path resource [activiti.cfg.xml]
2013-12-14 11:33:57 PM org.activiti.engine.impl.db.DbSqlSession executeSchemaResource
INFO: performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
2013-12-14 11:33:57 PM org.activiti.engine.impl.db.DbSqlSession executeSchemaResource
INFO: performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
2013-12-14 11:33:57 PM org.activiti.engine.impl.db.DbSqlSession executeSchemaResource
INFO: performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
2013-12-14 11:33:57 PM org.activiti.engine.impl.ProcessEngineImpl <init>
INFO: ProcessEngine default created


Observations:
1) H2 database is used instead of production database, hence (correct) activiti.cfg.xml from test directory seams to be used.
2) Process engine "default" is created as an instance of
org.activiti.engine.impl.ProcessEngineImpl
– but according to test configuration, it should be an instance of
org.activiti.spring.ProcessEngineFactoryBean
.
3)
initi
from
TestDataGenerator
is not called (no log in output) and, consequently, the test fails.

Any ideas? How to activate the
TestDataGenerator
(and previously the right process engine)?

Thank you for any thoughts,
best regards,
kai
2 REPLIES 2

frederikherema1
Star Contributor
Star Contributor
1) That what you want, right?
2) org.activiti.spring.ProcessEngineFactoryBean is just a factory-bean. If you know your way around spring, it will create an instance of a bean, when the "getInstance" is called. So it's a factory for other types of beens, and in this case, it creates ProcessEngine(Impl) beans. This is exactly what it's designed to do.
3) Spring will only call the init-method if the spring-context is started and the bean is created. The way the "default" activiti-configuration works is that it does NOT boot an application-context. Rather, it just uses the bean-definitions in the activiti.cfg.xml file to extract the processEngine itself. If you want to use activiti in a spring-context, you should boot up the engine USING the application-context and depend on that bean instance, instead of depending on the ProcessEngines.getDefault().

Fortunatly, we have base spring-tests for that as well, so you can point to a valid spring-context file (which you already have). An example of this can be found in the org.activiti.spring.test.components.ProcessStartingBeanPostProcessorTest class:


/**
* @author Josh Long
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:smileysurprised:rg/activiti/spring/test/components/ProcessStartingBeanPostProcessorTest-context.xml")
public class ProcessStartingBeanPostProcessorTest {

private Logger log = LoggerFactory.getLogger(getClass());

@Autowired
private ProcessEngine processEngine;

@Autowired
private ProcessInitiatingPojo processInitiatingPojo;

@Autowired
private RepositoryService repositoryService;

@Before
public void before() {
   repositoryService.createDeployment()
     .addClasspathResource("org/activiti/spring/test/autodeployment/autodeploy.b.bpmn20.xml")
     .addClasspathResource("org/activiti/spring/test/components/waiter.bpmn20.xml")
     .deploy();
}

You can just used the injected process-engine, instead of depending on the base-class to do the initialisation.

kaihuener
Champ in-the-making
Champ in-the-making
Frederik – again you, thank you so much! Will have to send you some christmas presents for all this great support, right?
For those who have a similar question: I change the test as follows:
<code>import static org.junit.Assert.assertTrue;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.test.ActivitiRule;
import org.junit.Rule;
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.SpringJUnit4ClassRunner;
import cdq.cdl.bpr.shared.Constants;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:activiti.cfg.xml")
public class TestBasic {

@Rule
public ActivitiRule activitiRule = new ActivitiRule();

@Autowired
private ProcessEngine processEngine;

@Test
public void testLogin() {

  boolean check = activitiRule.getIdentityService().checkPassword("foo"; "bar");
  assertTrue(check);
}
}</code>
I also had to explicitly add spring-context dependency with "3.2.5" version to the project's POM file because (in my case), only an older version was resolved by maven. But this may be due to my specific settings – here just as a hint.

So far – thank you and best regards,
Kai