I got a problem with my Dao-Test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"/cmn-dao-spring.xml"})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class ScoreDaoTest extends TestCase {
#Autowired
private ScoreDao mScoreDao;
#Autowired
private ScoreCreator mScoreCreator;
#Autowired
private QuestionCreator mQuestionCreator;
#Override
protected void setUp() throws Exception {
super.setUp();
}
#Test
public void testLoadAllScore() throws Exception {
List<Score> lAllScore = mScoreDao.loadAllScore(0, 0);
Assert.assertTrue(lAllScore.isEmpty());
}
#Test
public void testSaveScore() throws Exception {
Question question = mQuestionCreator.createQuestion(49954854L, new Date(), "Wer bist Du?", "Jörg", "Anja", "Stefan", "Willi", 3, true, false, 1, "DE", "DE_QZ");
Assert.assertNotNull(question);
mScoreDao.saveScore(mScoreCreator.createScore(-1L, null, "Stefan", 1033, 27, "Wuhuuuu", question));
List<Score> lAllScore = mScoreDao.loadAllScore(0, 1);
Assert.assertFalse(lAllScore.isEmpty());
}
}
Every time I run my test class the data is saved permanently. But I don't want that for my test classes.
I don't see the problem.
Your tests are not transactional, so Spring doesn't have any transaction to rollback.
Add #Transactional to the test methods (or to the test class if you want all its test methods to be transactional).
Related
Can someone help me writing JUnit for the below serviceImpl class
#Component
public class ProcessStatusMasterServiceImpl implements ProcessStatusMasterService {
#Autowired
private ProcessStatusRepository processStatusRepository;
#Autowired
private ApplicationContext applicationContext;
public ProcessAndMacroStatus findProcessMaster(StatusConstant statusConstants) {
ProcessStatusMasterService thisBean = (ProcessStatusMasterService)this.applicationContext.getBean(ProcessStatusMasterService.class);
List<ProcessAndMacroStatus> processStatuses = thisBean.findProcessMasterByCategory(statusConstants.getCategory());
Optional<ProcessAndMacroStatus> processStatusOpt = processStatuses.stream().filter(f -> f.getProcessAndMacroStatusKey().equals(statusConstants.getKey())).findFirst();
if (processStatusOpt.isPresent())
return processStatusOpt.get();
throw new IllegalArgumentException("Unable to find status: " + statusConstants.getKey() + " for category: " + statusConstants.getCategory());
}
#Cacheable({"ProcessStatusMasterCache"})
public List<ProcessAndMacroStatus> findProcessMasterByCategory(String category) {
List<ProcessAndMacroStatus> processStatuses = this.processStatusRepository.findByProcessMacroStatusCategory(category);
return processStatuses;
}
}
below is the code i am trying, but i am getting NPE for line when(thisBean.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
Reason for this variable thisbean is null
#RunWith(MockitoJUnitRunner.class)
public class ProcessStatusMasterServiceImplTest {
#Mock
ProcessStatusRepository processStatusRepository;
#Mock
ApplicationContext applicationContext;
#InjectMocks
ProcessStatusMasterServiceImpl processStatusMasterServiceImpl;
#Test
public void findProcessMaster() throws Exception {
ProcessStatusMasterService thisBean = (ProcessStatusMasterService)this.applicationContext.getBean(ProcessStatusMasterService.class);
List<ProcessAndMacroStatus> processStatuses=new ArrayList<ProcessAndMacroStatus>();
when(thisBean.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
processStatusMasterServiceImpl.findProcessMaster(StatusConstant.GROUP_STATUS_SUCCESS);
}
}
I think you're trying to mock the behaviour of the tested entity itself instead of the mocked dependencies. I'd try mocking it like this:
#Test
public void findProcessMaster() throws Exception {
List<ProcessAndMacroStatus> processStatuses=new ArrayList<ProcessAndMacroStatus>();
when(processStatusRepository.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
processStatusMasterServiceImpl.findProcessMaster(StatusConstant.GROUP_STATUS_SUCCESS);
}
Please remove your thisBean in your production code, just use this. instead.
List<ProcessAndMacroStatus> processStatuses = this.findProcessMasterByCategory(statusConstants.getCategory());
and modify your test
#Test
public void findProcessMaster() throws Exception {
List<ProcessAndMacroStatus> processStatuses = new ArrayList<ProcessAndMacroStatus> ();
when(processStatusRepository.findProcessMasterByCategory(StatusConstant.GROUP_STATUS_SUCCESS.getCategory())).thenReturn(processStatuses);
processStatusMasterServiceImpl.findProcessMaster(StatusConstant.GROUP_STATUS_SUCCESS);
// your assert
}
Test case fails to retry multiple times (2), it tries once and the exception is thrown
my application class has EnableRetry annotation
#SpringBootApplication
#ComponentScan("com.***")
#EnableJpaAuditing
#EnableRetry
public class Application {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
}
This is the service class that has the method I want to retry.
#Service
#RequiredArgsConstructor
#Slf4j
#EnableRetry //just in case, this didn't help though!!
public class DataSetService {
//some objects
private int count;
.....
#Scheduled(fixedRate = 86400000)
#Retryable(value = {OptimisticLockException.class}, maxAttemptsExpression = 2, backoff =
#Backoff(delayExpression = 1000))
public void updateDataSetExp() {
LOG.info("Count : " + count++); //Expecting this count to be 3 after re-tries
Date dateBeforeExpiry = new Date(System.currentTimeMillis() - THIRTY_DAYS_IN_MS);
List<DataSet> expiredDataSets =
dataSetRepository.findByCreatedAtBefore(dateBeforeExpiry);
for (DataSet expiredDs : expiredDataSets) {
expiredDs.setExpired(true);
dataSetRepository.save(expiredDs);
}
}
}
#Recover
public void updateDataSetExpFallback(OptimisticLockException e) {
LOG.error("Optimistic locking issues found");
}
My test case
#RunWith(SpringRunner.class)
#SpringBootTest
public class DataSetServiceRunnerTest {
#Autowired
private DataSetService dataSetService;
DataSetCreateRequest dataSetCreateRequest;
DataSet dataSet;
#MockBean
DataSetRepository dataSetRepository;
//all other mock beans that are required
#Before
public void setup(){
dataSetService = new DataSetService(dataReferenceRepository, dataSetRepository,
principalService,userInfoService, ccStorageService, elasticConfiguration,
clusterRepository, encryptionService, awsService);
dataSet = new DataSet();
}
#Test
public void testUpdateDataSetExpiryOptimisticLock(){
List<DataSet> expiredDataSetList = new ArrayList<>();
expiredDataSetList.add(dataSet);
when(dataSetRepository.findByCreatedAtBefore(any(Date.class)))
.thenReturn(expiredDataSetList);
when(dataSetRepository.save(any(DataSet.class)))
.thenThrow(OptimisticLockException.class);
try {
dataSetService.updateDataSetExp();
} catch (OptimisticLockException e){
System.out.println("Exception caught");
}
verify(dataSetRepository, times(3)).save(dataSet);
verify(dataSetRepository, times(3)).findByCreatedAtBefore(any(Date.class));
}
}
I am expecting dataSetRepository.findByCreatedAtBefore method to be invoked 3 times and then the exception is thrown but in my case, it is only invoked once. also, the count is expected to be 3 but is 1.
I've tried looking into other posts and followed the documentation around Retryable but didn't help. Can someone provide some pointers.
In your test case setup() is not required ideally because #SpringBootTest will load Spring context and all Beans will be initialized explicitly.
Also, I tried to replicate your setup and it seems to be working fine with and without #Scheduled
#Slf4j
#Service
#AllArgsConstructor
public class RetryDirectService {
private final TestService testService;
#Retryable(value = NumberFormatException.class, maxAttempts = 4, backoff = #Backoff(500))
#Scheduled(fixedRate = 10000)
public String getData() {
return testService.getData();
}
#Recover
public String recoverData(String appender) {
log.info("Calling recoverData");
return "DEFAULT";
}
}
#SpringBootTest
public class RetryDirectServiceTest {
#Autowired
private RetryDirectService retryDirectService;
#MockBean
private TestService testService;
#Test
public void testShouldRetryTillMaxAttemptsAndCallsRecoveryBlock(){
//Given
Mockito.when(testService.getData()).thenThrow(new NumberFormatException());
//When
retryDirectService.getData();
//Then
verify(testService, Mockito.times(4)).getData();
}
}
The only deviation was that with #Scheduled, getData() was called 5 times. Which is expected. 4 times for retry and one time when triggered by the scheduler.
For more detail in Retry setup plase refer this post
This might have been coded wrongly, but any idea how it should be done is appreciated.
I have this class TestClass which needs to inject many service class. Since I can't use #BeforeClass on #Autowired objects, I result on using AbstractTestExecutionListener. Everything was working as expected but when I'm on #Test blocks, all objects are evaluated null.
Any idea how to solve this?
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { ProjectConfig.class })
#TestExecutionListeners({ TestClass.class })
public class TestClass extends AbstractTestExecutionListener {
#Autowired private FirstService firstService;
// ... other services
// objects needs to initialise on beforeTestClass and afterTestClass
private First first;
// ...
// objects needs to be initialised on beforeTestMethod and afterTestMethod
private Third third;
// ...
#Override public void beforeTestClass(TestContext testContext) throws Exception {
testContext.getApplicationContext().getAutowireCapableBeanFactory().autowireBean(this);
first = firstService.setUp();
}
#Override public void beforeTestMethod(TestContext testContext) throws Exception {
third = thirdService.setup();
}
#Test public void testOne() {
first = someLogicHelper.recompute(first);
// ...
}
// other tests
#Override public void afterTestMethod(TestContext testContext) throws Exception {
thirdService.tearDown(third);
}
#Override public void afterTestClass(TestContext testContext) throws Exception {
firstService.tearDown(first);
}
}
#Service
public class FirstService {
// logic
}
For starters, having your test class implement AbstractTestExecutionListener is not a good idea. A TestExecutionListener should be implemented in a stand-alone class. So you might want to rethink that approach.
In any case, your current configuration is broken: you disabled all default TestExecutionListener implementations.
To include the defaults, try the following configuration instead.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ProjectConfig.class)
#TestExecutionListeners(listeners = TestClass.class, mergeMode = MERGE_WITH_DEFAULTS)
public class TestClass extends AbstractTestExecutionListener {
// ...
}
Regards,
Sam (author of the Spring TestContext Framework)
I'm having troubles setting this to work. Basically I want when a tests finishes running for the database to be in the exact same state as before. This happens when using Spring/Hibernate managed sessions and connections, but not for DBUnit. I've tried lots of things and at this point I was doing something like wrapping the shared datasource in TransactionAwareDataSourceProxy and executing the load dataset manually instead of using #DatabaseSetup.
this.databaseConnection = new DatabaseConnection(dataSource.getConnection());
IDataSet xmlFileDataSet = new FlatXmlDataSetBuilder().build(getClass().getResourceAsStream("/dataset.xml"));
DatabaseOperation.REFRESH.execute(databaseConnection, xmlFileDataSet);
And it simply doesn't work. I've checked the dataSource object and it's a TransactionAwareDataSourceProxy instance so everything should be in place. All the data in the dataset is committed and persisted and all the data added/modified inside the spring managed session is not.
Does anyone have a clue what I might be missing or any did this before and ran into the same troubles?
Current code (tried with and without TransactionAwareDataSourceProxy).
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {
RecipeManagementITConfig.class,
SpringJpaTestConfig.class,
DatabaseITConfig.class
},
initializers = {PleaseWork.class})
#TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
#TransactionConfiguration(defaultRollback = true)
#Transactional
public class DefaultIngredientServiceIT {
#Autowired
protected DataSource dataSource;
#Before
public void init() throws Exception {
System.out.println("> " + dataSource); // org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy#d4ce346
dbTester = new DataSourceDatabaseTester(dataSource);
dbTester.setDataSet(getDataSet());
dbTester.setSetUpOperation(DatabaseOperation.REFRESH);
dbTester.onSetup();
}
#After
public void destroy() throws Exception {
dbTester.onTearDown();
}
private IDataSet getDataSet() throws Exception {
return new FlatXmlDataSetBuilder().build(getClass().getResourceAsStream("/dataset.xml"));
}
#Transactional
#Test
public void testDeletionOfIngredients() {
(...)
}
}
Try using a DataSourceDatabaseTester like this:
public class MyTestCase {
#Autowired
private DataSource dataSource;
private IDatabaseTester dbTester;
#Before
public void init() throws Exception {
dbTester = new DataSourceDatabaseTester( getDataSource() );
dbTester.setDataSet( getDataSet() );
dbTester.onSetUp();
}
#Destroy
public void destroy() throws Exception {
dbTester.onTearDown();
}
private IDataSet getDataSet() throws Exception {
return new FlatXmlDataSet(new FileInputStream("dataset.xml"));
}
}
Hi I'm using Spring and CDI.
In my unit test I want to test a Class that uses the #Autowired annotation.
Problem is if I create a instance of this class and call a method all annotated objects are null.
In basic the annotation works. Just whithin my unit test it doesn't
This is my Unit Test. In here Autowired works. In my test I create an instance of the DemoConsumerBean.class and call the method requestJobsFromPublishedJobsApi in here I have also some Autowired declaration. Problem is all instances are null!
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles("development")
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, FirstbirdTestExecutionListener.class, FlywayTestExecutionListener.class })
#ContextConfiguration(locations = { "classpath:hibernate-spring.xml" })
#FlywayTest
public class DemoConsumerBeanTest extends AbstractJUnit4SpringContextTests {
#Autowired
private CustomerManager customerManager;
#Autowired
private DemoDetailsManager demoDetailsManager;
#Before
public void setup() {
CamelContext context = new DefaultCamelContext();
exchange = new DefaultExchange(context);
}
#Test
public void requestJobsFromPublishedJobsApiTest() throws NoSuchDataException {
DemoConsumerBean demoConsumerBean = new DemoConsumerBean();
customer = new Customer();
customer.setCustomerId(15);
customer = customerManager.getCustomerById(customer);
// This one works
DemoDetails demoDetails = demoDetailsManager.getDemoDetailsByCustomerId(customer);
demoConsumerBean.requestJobsFromPublishedJobsApi(exchange, customer);
PublishedJobs apiJobs = exchange.getIn().getBody(PublishedJobs.class);
assertNotNull(apiJobs);
}
}
public class DemoConsumerBean {
#Autowired
protected CustomerManager customerManager;
#Autowired
protected DemoDetailsManager demoDetailsManager;
#Autowired
protected MessageLogManager messageLogManager;
public void requestJobsFromPublishedJobsApi(Exchange exchange, Customer customer) throws NoSuchDataException {
//this one is null!
DemoDetails demoDetails = demoDetailsManager.getDemoDetailsByCustomerId(customer);
PublishedJobs jobs = null;
if (demoDetails == null || StringUtils.isBlank(demoDetails.getDemoApiUrl())) {
throw new NoSuchDataException("No demo data found for customer " + customer.getCustomerFirstbirdId());
}
....
}
}
Using new in new DemoConsumerBean(); bypasses spring, that's your issue.
Either use a DemoConsumerBean instance from spring (i.e. autowired in the test) or add setters and use them to "manually autowire" in DemoConsumerBean in your test:
#Test
public void requestJobsFromPublishedJobsApiTest() throws NoSuchDataException {
DemoConsumerBean demoConsumerBean = new DemoConsumerBean();
demoConsumerBean.setCustomerManager(this.customerManager)
// etc
Some reading: Spring framework reference - The IoC container