I am trying to make a unit test on a method from a DAO class. Dao class is using JDBC. I am trying to unit test it but without using test data base. I must test it using some data structure for storing all the information.
public class UserProfilesDao extends JdbcDaoSupport {
#Autowired
private MessageSourceAccessor msa;
public long getUserServiceId(long userId, int serviceId) {
String sql = msa.getMessage("sql.select.service_user_id");
Object[] params = new Object[] { userId, serviceId };
int[] types = new int[] { Types.INTEGER, Types.INTEGER };
return getJdbcTemplate().queryForLong(sql, params, types);
}
}
getJdbcTemplate() appears to be a method that you want to mock out.
In your unit test, declare a UserProfilesDao member as follows:
#Spy
private UserProfilesDao classToTest;
the #Spy is a mockito annotation.
in your unit test declare a setup method as follows:
#Before
public void preTestSetup()
{
MockitoAnnotations.initMocks(this);
doReturn(what ever you want).when(classToTest).queryForLong(
any(xxx.class),
any(yyy.class),
any(zzz.class));
}
where xxx, yyy, and zzz are the queryForLong parameter types.
You can store data in DTO Objects and maintain DTOs in a Map with proper keys.
For test, retrieve data from map using key according to your need!
Related
I am creating Unit Test for my ServiceImpl methods and I try to create a unit test for update method. However, I am not sure how should I test this method. It returns DTO of corresponding entity, but I have really no idea if I should use #Spy or #Captor. If I set a mock variable and then try to retrieve it and update its value, I will need to retrieve the same record to check its updated value.
I am new in testing and I have not found a proper example for update method. Any help would be appreciated.
public CompanyDTO update(CompanyRequest companyRequest, UUID uuid) {
final Company company = companyRepository.findByUuid(uuid)
.orElseThrow(() -> new EntityNotFoundException(COMPANY));
company.setName(companyRequest.getName());
final Company savedCompany = companyRepository.save(company);
return new CompanyDTO(savedCompany);
}
Update: Finally I make it worked, but I am not sure for some parts. Is there anything missing or redundant in the following test method?
#InjectMocks
private CompanyServiceImpl companyService;
#Mock
private CompanyRepository companyRepository;
#Captor
ArgumentCaptor<Company> companyCaptorEntity;
#Test
public void testUpdate() {
final UUID uuid = UUID.randomUUID();
final CompanyRequest request = new CompanyRequest();
request.setName("Updated Company Name");
final Company company = new Company();
company.setName("Company Name");
when(companyRepository.findByUuid(uuid))
.thenReturn(Optional.ofNullable(company));
//??? Do we need this?
when(companyRepository.save(any())).thenReturn(company);
CompanyDTO result = companyService.update(request, uuid);
Mockito.verify(companyRepository).save(companyCaptor.capture());
Company savedCompany = companyCaptor.getValue();
assertEquals(request.getName(), savedCompany.getName());
}
More importantly than the return type of the update() method, I believe you should test the values of the entity passed to the save() method of your mock repository (I assume you have one).
For this, you can use ArgumentCaptor.
For testing the return logic of your update() method, you can simply assign its result in your test to a response object. You can then compare this object with the values of your input object.
Here is an example of both testing the arguments to the save method of your mock repository and the return of your update method (they should be two different unit tests):
#Test
void test() {
// Arrange
ArgumentCaptor<Entity> entityArgumentCaptor = ArgumentCaptor.forClass(Entity.class);
InputDto inputDto = prepareTestInput();
// Act
ResponseDto responseDto = service.update(inputDto);
verify(repositoryMock, times(1)).save(entityArgumentCaptor.capture());
// Assert
Entity savedEntity = argumentCaptor.getValue();
assertEquals(input.getVariable1(), savedEntity.getVariable1());
// .....
// compare ResponseDto and InputDto too
}
I am new to junit testing using mockito in java. I have been stuck at one point.
I have one abstract class AbstractA which needs to test.
Implementation of AbstractA as below.
public abstract class AbstractA implements ADao {
#Autowired
NamedParameterJdbcTemplate jdbcTemplate;
#Override
public List<String> getColumns(Set<String> ids) {
String sql = query();
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("ids", ids);
return jdbcTemplate.query(sql, paramMap, rowMapper());
}
abstract protected String query();
abstract protected AbstractIpRowMapper rowMapper();
}
And a test class for above is AbsractATest
public class AbsractATest {
#InjectMocks
AbsractA abstractA;
#Mock
NamedParameterJdbcTemplate jdbcTemplate;
#Mock AbstractIpRowMapper abstractIpRowMapper;
#Before
public void setUp() throws IOException, SQLException {
abstractA=Mockito.mock(AbsractA.class, Mockito.CALLS_REAL_METHODS);
jdbcTemplate=mock(NamedParameterJdbcTemplate.class);
List<String> idsinput=new ArrayList<String>();
idsinput.add("123");
idsinput.add("124");
idsinput.add("125");
Set<String> ids=new LinkedHashSet<String>();
ids.add("123");
ids.add("124");
ids.add("125");
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("ids", ids);
String query="select ids from tableA where ids=:ids";
when(abstractA.query()).thenReturn(query);
when(jdbcTemplate.query(query, paramMap,rowMapper())).thenReturn(idsinput);
org.springframework.test.util.ReflectionTestUtils.setField(abstractA, "jdbcTemplate", jdbcTemplate);
}
protected AbstractIpRowMapper rowMapper() {
return absractIpRowmapper;
}
But after running this test case I am getting empty value for
abstractA.getColumns();
Please help me to understand what I should need to do in above case.
Run doCallRealMethod().when(abstractA).getColumns(); in the unit test
You don't need to test abstract class tdd knows nothing about abstract classes, make it normal class and only you have same code duplication with two or more class lift it up to abstract, test for this class will not change. Specify sql query string and IPRowMapper as constructor parameters this simplify and make your code more clean. Second, you don't need such complicated setup for tests, you need only to verify interactions, not return value, verify only NamedParameterJdbcTemplate mock, whats values passed to it.
I am trying to unit test a void method which gets data from database, formats into map and passes onto another class.
I have mocked out the database call and returned my own data, and I want to inspect the map which has been formatted contains the right number of elements and keys in right locations.
I have tried playing around with argumentCaptor to do this but struggling to get my head round it.
Method to test:
public class MyClass {
#Autowired
private Dao dao;
#Autowired
private AnotherClass anotherClass;
public void format(String, Date) {
Map<Object,Object> map = getDataAndFormat(String, Date);
anotherClass.doSomething(map);
}
private Map<Object, Object> getDataAndFormat(String, Date) {
Map map;
if (String.equals("A") {
map = dao.getData(Date);
}
else {
map = dao.getDataSomeThingElse(Date);
}
}
}
Any help much appreciated
Thanks,
so: This is what I have so far:
#InjectMocks
#Autowired
//class to test
private MyClass myClass;
#Mock
Dao dao;
#Captor
private ArgumentCaptor<String> argumentCaptor;
#Captor
private ArgumentCaptor<Date> argumentCaptorB;
public void testFormat()
{
when(dao.getData(Matchers.any())).thenReturn(data());
myClass.format("A",new Date());
}
So i want to use argument captors (but not entirely sure how to) to get the map from the format method call and inspect the returned map. The code i currently have is hitting all my code but I can't assert on anything hence why i wanted to check the map contains what I expect it to. Hope that makes sense
It appears that what you want to do is to confirm the contents of the map that is passed to AnotherClass.
If AnotherClass is an interface, you can create a mock instance of AnotherClass and inject it into your MyClass. You can then verify that it has been called with your arguments of choice:
Mockito.verify(mockAnotherClass).doSomething(expectedMap);
I was playing with org.springframework.data.jpa.domain.Specifications, it's just a basic search :
public Optional<List<Article>> rechercheArticle(String code, String libelle) {
List<Article> result = null;
if(StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(libelle)){
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
}else{
if(StringUtils.isNotEmpty(code)){
result= articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)));
}else{
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteLibelle(libelle)));
}
}
if(result.isEmpty()){
return Optional.empty();
}else{
return Optional.of(result);
}
}
And that's actually working fine but I'd like to write unit tests for this method and I can't figure out how to check specifications passed to my articleRepository.findAll()
At the moment my unit test looks like :
#Test
public void rechercheArticle_okTousCriteres() throws FacturationServiceException {
String code = "code";
String libelle = "libelle";
List<Article> articles = new ArrayList<>();
Article a1 = new Article();
articles.add(a1);
Mockito.when(articleRepository.findAll(Mockito.any(Specifications.class))).thenReturn(articles);
Optional<List<Article>> result = articleManager.rechercheArticle(code, libelle);
Assert.assertTrue(result.isPresent());
//ArgumentCaptor<Specifications> argument = ArgumentCaptor.forClass(Specifications.class);
Mockito.verify(articleRepository).findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
//argument.getValue().toPredicate(root, query, builder);
}
Any idea?
I was having almost the same problems as you had, and I changed my class that contains Specifications to be an object instead of just one class with static methods. This way I can easily mock it, use dependency injection to pass it, and test which methods were called (without using PowerMockito to mock static methods).
If you wanna do like I did, I recommend you to test the correctness of specifications with integration tests, and for the rest, just if the right method was called.
For example:
public class CdrSpecs {
public Specification<Cdr> calledBetween(LocalDateTime start, LocalDateTime end) {
return (root, query, cb) -> cb.between(root.get(Cdr_.callDate), start, end);
}
}
Then you have an integration test for this method, which will test whether the method is right or not:
#RunWith(SpringRunner.class)
#DataJpaTest
#Sql("/cdr-test-data.sql")
public class CdrIntegrationTest {
#Autowired
private CdrRepository cdrRepository;
private CdrSpecs specs = new CdrSpecs();
#Test
public void findByPeriod() throws Exception {
LocalDateTime today = LocalDateTime.now();
LocalDateTime firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDateTime lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
List<Cdr> cdrList = cdrRepository.findAll(specs.calledBetween(firstDayOfMonth, lastDayOfMonth));
assertThat(cdrList).isNotEmpty().hasSize(2);
}
And now when you wanna unit test other components, you can test like this, for example:
#RunWith(JUnit4.class)
public class CdrSearchServiceTest {
#Mock
private CdrSpecs specs;
#Mock
private CdrRepository repo;
private CdrSearchService searchService;
#Before
public void setUp() throws Exception {
initMocks(this);
searchService = new CdrSearchService(repo, specs);
}
#Test
public void testSearch() throws Exception {
// some code here that interact with searchService
verify(specs).calledBetween(any(LocalDateTime.class), any(LocalDateTime.class));
// and you can verify any other method of specs that should have been called
}
And of course, inside the Service you can still use the where and and static methods of Specifications class.
I hope this can help you.
If you are writing Unit Tests then you should probably mock the call to findAll() method of articleRepository Class using a mocking framework like Mockito or PowerMock.
There is a method verify() using which you can check if the mock is invoked for the particular parameters.
For Example, if you are mocking the findAll() method of articleRepository Class and want to know if this method is called with particular arguments then you can do something like:
Mokito.verify(mymock, Mockito.times(1)).findAll(/* Provide Arguments */);
This will fail the test if mock has not been called for the arguments that you provided.
Your problem is that you are doing too many things within that one method. You should have three different methods that work on articleRepository.
Then you can use mocking as the others suggest:
setup your mocks so that you know which call on articleRepository should be made
verify that exactly the expected calls are happening
Please note: these three methods should be internal; the main point there is: you can't test this method with ONE call from the outside; as it is doing more than one thing, depending on the input that you provide. Thus you need to create at least one test method for each of the potential paths in your code. And that becomes easier (from a conceptual point of view) when you separate your code into different methods.
here are examples of a methods :
public <T> T save(final T o){
return (T) sessionFactory.getCurrentSession().save(o);
}
public <T> T get(final Class<T> type, final Long id){
return (T) sessionFactory.getCurrentSession().get(type, id);
}
public <T> List<T> getFieldLike(final Class<T> type, final String propertyName,
final String value, final MatchMode matchMode) {
final Session session = sessionFactory.getCurrentSession();
final Criteria crit = session.createCriteria(type);
crit.add(Restrictions.like(propertyName, value, matchMode));
return crit.list();
}
Any tips on either unit or integration test these ? Pass in a mock session ?
About the only thing you could do in a unit test is mock Session and Criteria and set expectations - I've done this for a few cases using JMock and ended up having to write a Hamcrest matcher for the Restricitons. I'm not convinced there's much value in it, other than blindly increasing the test coverage.
On the other hand - writing an integration test here would be of definite use, set up an in memory database with some data and assert that the methods return the correct objects
An example for integration test for get():
// if you can inject the object:
// #Inject
// public MyTestDAO<MyType> dao;
//
#Test
public testGet() throws Exception {
Session session = HibernateUtils.getSessionFactory().getCurrentSession();
MyTestDAO<MyType> dao = new MyTestDAO<MyType>();
// if you use DI facility, check against null
// assertNotNull(dao)
MyType myType = dao.get(Test.class, 1L);
assertNotNull(myType);
assertEqual(myType, equalObj);
// more asserts?
}
if you use spring framework, you can use spring-test module to use DI using spring context and class runner:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:spring.xml"})
By your question I assume you are managing your sessions yourself. I will talk about the unit testing part. Integration tests can be done on an in memory database during integration. H2 or Derby are one of the most used ones as far as I know.
You can go by passing a mock session to your DAO, but what will happen if one of your colleagues writes a unit test and forgets to pass a mock session? Do you hit database? If you DO NOT want to hit database, this approach can be a problem
What a better approach would be to use an abstract factory pattern to even ACQUIRE the dao. Basically your code is currently like this:
MyDao.get(someId);
However, you can go in the following way:
If you define your Dao first like this:
public interface IDao <SomeGenerics> {
public <T> T get(Class<T> type, ID key);
//more generic methods
}
Then you can have an implementation of the Dao, which is like this:
public class MyDao <SomeGenerics> implements IDao<SomeGenerics> {
public <T> T get(Class<T> type, ID key){
//some real session stuff
}
//...more real session stuff
}
Then in your unit tests you can define a mock of your IDao interface, kinda like this:
public class MyDaoMock <SomeGenerics> implements IDao<SomeGenerics> {
//this thingy can hold a small array of mock instances
private ArrayList<T> mockInstances;
public <T> T get(Class<T> type, ID key){
//some fake stuff, kinda like this;
for (T mockInstance : mockInstances) {
if ( mockInstance.getId().equals(key) ) {//here i assume your T has a method getId, you figure out the kinks
return mockInstance;
}
}
//if not found, emulate your persistence's behavior, return null, throw an exception or do whatever
return null;
}
//...more fake stuff
}
Now you have an interface and two implementations, one for your production code and one for your unit tests. Now all you have to do is to implement the factory pattern to give you the right dao in production and in testing code.