How to implements unit tests for SQLQueryFactory query? - java

It is my repository class implementation, Im using querydsl-sql for the DB persistence, It works very good when run the spring-boot project, but i need to strcuture unit test for this fragment of code, I try to use Mocks but i dont now how use this for SQLQueryFactory class or use other types of tools for unit test
#Repository
#Transactional
public class ContactRepository implements IContactRepository {
#Inject
SQLQueryFactory queryFactory;
#Transactional(readOnly = true)
#Override
public Tuple getContactInformationQuery(String memberCode) {
return queryFactory
.select(
sspcotdatconper.direccionprin,
sspcotdatconper.numtelcelu)
.from(sspcotdatconper)
.innerJoin(sspcotperson)
.on(sspcotperson.codigoper.eq(sspcotdatconper.codigoper)
.and(sspcotdatconper.codigotipocontac.eq("GTH"))
.and(sspcotdatconper.est.eq("ACT")))
.innerJoin(sspcotfun)
.on(sspcotfun.codigoper.eq(sspcotper.codigoper))
.where(sspcotfun.codigofun.eq(memberCode))
.fetchOne();
}
}

Related

Java spring Mockito does not mock MongoDb service

I have a service
#Service
public class ShopServiceImpl implements ShopService {
private ShopRepository shopRepository;
public ShopServiceImpl (ShopRepository shopRepository) {
this.shopRepository= shopRepository;
}
...
}
and I want to write test with mocked Mongo database to test the CRUD methods.
#RunWith(MockitoJUnitRunner.class)
public class GetShopServiceTest {
#Mock
private ShopRepository ShopRepository;
#InjectMocks
private ShopServiceImpl shopService;
#Test
public void randomTest() {
...
Shop shopSaved = shopService.save(shop);
List<Shop> shopsRetrieved = shopService.listShops();
}
}
But this mocked service does not save or retrieve saved record. I do not have any configurations that relate to mocked mongo db, but tried them and they didin't work. What to do?
You can use #DataMongoTest.
Sample Implementation

Android Hilt Testing: Bind different database per test

I am currently writing tests for my Android application using Hilt. The App got a Room database, which I want to use in my test classes. Furthermore, I want in some test classes an empty database and in others a database with test values. My question is if I can define in my Test, which provider (empty/full DB) is used for all injections that are happening in the test class?
I tried using the #Named annotation, Qualifiers, and #BindValue. With the first two I am able to use the correct provider for my database, but I do not know how this could be used when injecting my repository. With #BindValue I am not sure if this can be used for this at all.
Here is some simplified code of my problem:
TestDatabaseModule:
#Module
#TestInstallIn(components = SingletonComponent.class, replaces = DatabaseModule.class)
public class TestDatabaseModule {
// Provide empty DB
#Singleton
#Provides
AppDatabase provideInMemoryDbEmpty(#ApplicationContext Context context) {
return Room.inMemoryDatabaseBuilder(context, AppDatabase.class).build();
}
// Provide populated DB
#Singleton
#Provides
AppDatabase provideInMemoryDbFull(#ApplicationContext Context context, Provider<AppDatabase> databaseProvider) {
// AppDatabasePopulateCallback adds some test data
return Room.inMemoryDatabaseBuilder(context, AppDatabase.class).addCallback(new AppDatabasePopulateCallback(databaseProvider)).build();
}
}
Module providing DAO and repository
#InstallIn(SingletonComponent.class)
#Module
public class AccessModule {
#Singleton
#Provides
MyDao provideMyDao(AppDatabase appDatabase) {
return appDatabase.myDao();
}
#Provides
MyRepository providesMyRepository(MyDao myDao) {
return new MyRepository(myDao);
}
}
Test Class one:
#HiltAndroidTest
#SmallTest
public class TestOne {
#Rule
public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
#Rule
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
// Inject repository that uses empty DB
#Inject
MyRepository myRepository;
#Before
public void createDb() {
hiltRule.inject();
}
#Test
public void testOne() {
// Use my repository with the empty database
}
Test class two:
#HiltAndroidTest
#SmallTest
public class TestTwo {
#Rule
public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
#Rule
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
// Inject repository that uses populated DB
#Inject
MyRepository myRepository;
#Before
public void createDb() {
hiltRule.inject();
}
#Test
public void testTwo() {
// Use my repository with the full database
}
So in the TestOne class, I want to use the repository that can access the empty database, and in the TestTwo class the repository that uses the database with test data.
I know I could populate the database in every test I want to use the data. That is what I will do if it is not possible with Hilt. I am glad for any advice to solve my problem or someone answering that I am on the wrong track if it is not possible.
Thank you!

Integration test for spring jdbc

Let's say we have a service layer :
#Service
public class MyServiceImpl implements MyService {
#Autowired
private MyDAO myDAO;
#Transactional
public void myMethod(SomeObject someObject) {
myDAO.insertIntoMyDb(someObject);
}
}
Let us say myDAO uses spring jdbc :
#Repository
public class MyDAOImpl implements MyDAO {
#Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
#Override
public void insertIntoMyDb(SomeObject object) {
// some code before this where we get query and param
int numberOfRowsUpdated = jdbcTemplate.update(query,param);
if(numberOfRowsUpdated != 1)
throw new Exception("Error while inserting a record in database. Actual records inserted : " + numberOfRowsUpdated);
}
}
I want to write 2 tests.
The first test will check my dao layer only. I want to make a jdbc call here , get data and verify. I don't want to mock them.
The second test is integration test. I want my service layer to call Dao layer. Note that there is transaction. Now this will give me data from DAO. Again DAO has to connect to db to get data.
I am using spring boot. My database properties are present in applicationITest.properties file.
How to do these 2 testing ? What is the correct annotations I have to use ? Can some one provide an example ?
a) Rollback will happen by default as long as you annotate your Test class with #Transactional. Documentation about Test-managed transactions.
sample test class:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = MyTestConfig.class)
#Transactional
public class MyClassTest {
//..
#Test
public void myTest() {
//..
}
//..
}
b) Yes you can enforce the commit using the #Commit (added in Spring 4.2) test annotation. Here's the documentation.

Testing JPA Entities

I want to know how to write Junit test for Spring Repository classes.
As example :
class-AccountMoveActionDet
Jpa interface-AccountMoveActionDetlJpaRepository
And I want to test this repository class work or not.Spring Jpa support some methods like
List findAll();
deleteAll();
I wrote a class just like below:
#RunWith(SpringJUnit4ClassRunner.class)
public class AccountTypeMovementJpaRepositoryTest extends AbstractJpaTest {
#Autowired
AccountTypeMovementJpaRepository accountTypeMovementJpaRepository;
#Override
public void test() {
executeSqlScript("/fixtures/accountTypeMovementJpa.sql");
assertEquals("accountTypeMovementJpaRepository Test", accountTypeMovementJpaRepository.findAll().size(),
JdbcTestUtils.countRowsInTable(getJdbcTemplate(), "COF5REP"));
}
}
Error creating bean with name
'com.gayan.cmp.jparepositories.test.AccountTypeMovementJpaRepositoryTest':
Please help me to resolve this.
If you use spring-boot 1.4 and above the best place to start, Testing the JPA slice :
#RunWith(SpringRunner.class)
#DataJpaTest
public class UserRepositoryTests {
#Autowired
private TestEntityManager entityManager;
#Autowired
private UserRepository repository;
#Test
public void findByUsernameShouldReturnUser() {
this.entityManager.persist(new User("sboot", "123"));
User user = this.repository.findByUsername("sboot");
assertThat(user.getUsername()).isEqualTo("sboot");
assertThat(user.getVin()).isEqualTo("123");
}
}

JMockit unable to capture spring data jpa repository calls

By using JMockit #Capturing, it was unable to capture call to any spring data jpa repository methods.
public interface UserRepository extends JpaRepository<UserEntity, Long> {
UserEntity findByName(String name);
}
public class DefaultUserService implements UserService {
public User getUser(Long id) {
return userRepo.findOne( id );
}
public User getUser(String name) {
return userRepo.findByName( name );
}
}
public class UserServiceTest extends AbstractServiceTest {
#Inject UserService userService;
**#Capturing UserRepository userRepo;**
#Test
public void getUser_ShouldReturnUserObject() {
**new Expectations() {{
userRepo.findByName(anyString);
result = new UserEntity(1l, null, null, null, null);
}};**
User user = userService.getUser("abc");
assertNotNull(user.getId());
assertEquals(1l, user.getId().longValue());
}
}
However by replacing
UserRepository
with
JpaRepository<UserEntity, Long>
in the test class, JMockit able to intercept call to any methods available in JpaRepository interface like findOne() or findAll().
But it just not able to capture calls to custom repository methods that extends JpaRepository such as findByName().
I prefer to use #Capturing for this scenario even though JMockit state-based testing such as MockUp and Deencapsulation can solve this issue because it is much more simpler.
Any one has any ideas to solve this issue?
Without knowing what AbstractServiceTest + Spring is doing with respect to the #Inject fields, I can't tell why #Capturing fails. Maybe Spring creates a proxy object which delegates to another, but even then...
Anyway, unit tests like these can be more easily written:
public class UserServiceTest
{
#Tested DefaultUserService userService;
#Injectable UserRepository userRepo;
#Test
public void getUser_ShouldReturnUserObject()
{
new Expectations() {{
userRepo.findByName(anyString);
result = new User(1l, null, null, null, null);
}};
User user = userService.getUser("abc");
assertNotNull(user.getId());
assertEquals(1l, user.getId().longValue());
}
}
Unless you want to perform integration testing, it's generally best to let the mocking tool (JMockit in this case) do the injection of mock objects into tested objects.

Categories

Resources