user2740224
user2740224

Reputation:

different behavior of method marked transactional in test and in controller

I have class CandidateService marked as @Transactional

@Transactional
@Service("candidateService")
public class CandidateService {

    @Autowired
    private CandidateDao candidateDao;

    ....

    public void add(Candidate candidate) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String login = auth.getName();
        User user =  utilService.getOrSaveUser(login);
        candidate.setAuthor(user);
        candidateDao.add(candidate);
    }
   ...
}

dao implementation:

@Override
    public Integer add(Candidate candidate) throws HibernateException{
        Session session = sessionFactory.getCurrentSession();
        if (candidate == null) {
            return null;
        }
        Integer id = (Integer) session.save(candidate);
        return id;

    }

if I write in @controller class:

@RequestMapping("/submitFormAdd")
    public ModelAndView submitFormAdd(
            Model model,
            @ModelAttribute("myCandidate") @Valid Candidate myCandidate,
            BindingResult result,
            RedirectAttributes redirectAttributes) {
        if (result.hasErrors()) {
            return new ModelAndView("candidateDetailsAdd");
        }

        myCandidate.setDate(new Date());
        candidateService.add(myCandidate);

    .....
    }

After executing this methods data put to database!

if I write test:

@ContextConfiguration(locations = {"classpath:/test/BeanConfig.xml"})
public class CandidateServiceTest extends AbstractTransactionalJUnit4SpringContextTests{

    @Autowired
    CandidateService candidateService;

    @BeforeClass
    public static void initialize() throws Exception{

        UtilMethods.createTestDb();

    }
    @Before
    public void setup() {
        TestingAuthenticationToken testToken = new TestingAuthenticationToken("testUser", "");
        SecurityContextHolder.getContext().setAuthentication(testToken);
    }

    @After
    public void cleanUp() {
        SecurityContextHolder.clearContext();
    }
    @Test
    public void add(){
        Candidate candidate = new Candidate();
        candidate.setName("testUser");
        candidate.setPhone("88888");
        candidateService.add(candidate);
        List<Candidate> candidates = candidateService.findByName(candidate.getName());
        Assert.assertNotNull(candidates);
        Assert.assertEquals("88888", candidates.get(0).getPhone());
    }
}

test is green but after executing I don't see data in my database.

Can you explain me why and how to fix it?

UPDATE

configuration:
<tx:annotation-driven transaction-manager="transactionManager" />

    <!-- Менеджер транзакций -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

Upvotes: 0

Views: 172

Answers (3)

Dax Joshi
Dax Joshi

Reputation: 143

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)

above your test class will not affect to database.

set or add defaultRollback = false to see data persisted in table.

Upvotes: 1

Prabhakaran Ramaswamy
Prabhakaran Ramaswamy

Reputation: 26094

After completion of test method the changes are rolled back. Test method database changes are reverted and you can do the other test with new data. You no need to worry about the model object with same id in different test cases.

If you need common data you can do with in setup() method that changes also not saved in the database.

Before executing test methods the setup() method will be called. if you have 3 test method then 3 times setup() method will be called.

sorry for my bad English.......

Upvotes: 0

anstarovoyt
anstarovoyt

Reputation: 8136

I think you should add TransactionConfiguration annotation with param defaultRollback = false

Upvotes: 0

Related Questions