Unit testing Spring 3 database methods - java

I have abstract class that defines database methods, such as inserts and updates, and a concrete class that implements it. The database configurations (dataSource, DatabaseTarget etc) are defined as beans in context.xml-file.
The database with its methods work in Controller when I'm using Spring 3 anotations by
private AbsractClass a;
Constructor:
#Autowired
public Controller(AbstractClass a) {
this.a =a;
}
...and a getter for a.
Calling database methods is done by
getA().insertValues();
But I would like to write Junit tests for my methods. Is there any example for this kind of situation? I have googled for hours.

If you want to test your controller methods without touching the database (which is the correct way), create a new class that extends the AbsractClass and pass it as argument to your Controller class, example:
CustomerController controller= new CustomerController(new InMemoryCustomerDao());
//call your actions and assert, all calls to the database will hit the InMemoryDao.
Another way is to use a Mock Object if you don't want to create extra fake classes in your project or you need to assert that these arguments are being correctly called.

Related

Creating an Abstract Interface around DB Connection

I was reading this article on Unit Testing. It seems pretty straightforward, but there was a section that interested me and I wanted to see if someone could please provide an explanation or example of what this means. I think I understand it but maybe not well enough.
Write test cases that are independent of each other. For example, if a class depends on a database, do not write a case that interacts with the database to test the class. Instead, create an abstract interface around that database connection and implement that interface with a mock object.
What does it mean to:
create an abstract interface around the db connection?
then implement it with a mock object?
I am more questioning the first part (1) but if someone can explain both parts that would be helpful. Thanks.
ONE: The "abstract data interface" simply means that you provide an interface with methods for storing and finding data in a business oriented way, rather than use the database connection directly. You can then implement this interface to store data in different ways: an sql database, a file based approach, etc. Such a class in some patterns is also referred to as "data access object" (DAO).
public interface PersonDao {
void store(Person personToStore);
Person findById(String id);
}
public class SqlPersonDao implements PersonDao {
#Override
void store(Person personToStore) {
// use database connection here ...
}
}
Basically in a unit test you always want to mock anything that is not your system under test and has a complex behaviour you cannot control. That is especially true for things like system time, for example if a class uses system time, for tests you want a way to inject a predefined time overriding the system clock.
TWO:
In unit tests you don't want to be affected by bugs in any dependency. For a unit using the PersonDao, the PersonDaowould be such a dependency. Rather than relying on the real implementation's behaviour, you want to exactly define the results you expect (using the notation of the Mockito mocking framework and the AssertJ validation framework here):
class MyUnitTest {
// system under test
MyUnit sut;
#Mock
PersonDao personDaoMock;
#BeforeEach
public setup() {
initMocks(this);
sut = new MyUnit("some", "parameters");
}
#Test
void myTest() {
// setup test environment using a mock
var somePerson = new Person("101", "John", "Doe");
doReturn(somePerson).when(personDaoMock.findById("101"));
// run test
var actualValue = sut.doSomething();
// check results
assertThat(actualValue).isNotNull();
}
}

(java)should/how I refactor this code?

I am working on a old application with n-tier architecture. I have a domain service like this:
public Class DomainServiceA{
//inject
private ObjectADao adao;
private ParamDao pdao;
//others dao needed
public List<DomainObjectA> getListDomainA(){
List<DtoA> listDto = adao.getListaDto();
Param someparam = pdao.getParamA();
//some code to change listDto to listDomainObject
return listDomainObject;
}
//some ohters services methodes
}
for testing this methode, I need to mock the DAO and the methode used in this methode. I want to refactor this code
public Class DomainServiceA{
public List<DomainObjectA> getListDomainA(Supplier<List<DtoA>> listDto, Param someparam){
//some code to change listDto to listDomainObject
return listDomainObject;
}
//some ohters services methodes
}
So I dont need mock the daos anymore, and I think it increase testablity and readability. but for calling this method/service, the presentation layer must call the persistence layer to build the supplier. This is bad, right? Should I not refactor the code, and test with mock?
If your refactor in this way, it means that the DomainServiceA is not a service any longer but a mapper that map a List of DTO to a List of domain objects because you pass DTOs in the method and you return domain objects in.
It changes the overall intention of the method.
It is not getListDomainA() but toListDomain().
So I dont need mock the daos anymore, and I think it increase
testablity and readability. but for calling this method/service
The logic of the invoked DAO is still present but it is on the above layer and you should also test it. So it just moves the issue somewhere else and makes your design unclear : presentation layer should not communicate with repository layer as a service layer exists but it does.
Mocking DAO/repositories is a normal thing and you want to mock them to test the core logic of the service calling it and also to make sure that the method is invoked as it should be.
If you want to focus unit tests on the DTO-domain mapping you could introduce a Mapper class that accepts the DTO List and make the service call it. In this way no mock is required to test the Mapper class.

Inject the same class with different parameters with Guice [duplicate]

This question already has an answer here:
Guice: inject different implementation depending on who is getting it?
(1 answer)
Closed 5 years ago.
I have 2 different classes(Cart and Payment) trying to use same database accessor class DBAccessor, as DBAccessor only contains logic to read and write data from a DB in a fixed format.
public class Cart{
#Inject
Cart(#Cart DBService db){
}
..
}
public class Payment{
#Inject
Payment(#Payment DBService db){
}
..
}
public class CartDBService implements DBService{
#Inject
public CartDBService(DBAccessor){
}
}
public class PaymentDBService implements DBService{
#Inject
public PaymentDBService(DBAccessor){
}
}
public class DBAccessor{
#Inject
public DBAccessor(String tableName){
}
}
I want to inject dependencies using guice in the give setup making sure everything is created by guice.
I am using binding annotation to inject different DBService instances for Cart and Payment.
bind(DBService.class).annotatedWith(Cart.class).to(CartDBService.class);
bind(DBService.class).annotatedWith(Payment.class).to(PaymentDBService.class);
How do I inject separate DBAccessor classes for cart and order to make sure they get correct table names injected.
The issue is with the design: class DBAccessor is doing too much work since it's reading different kind of data from different tables, now Guice is saving you by showing you that you were a bad boy...
Solution: implement two DBAccessor-classes, if they have common logic you can extract it to default methods in an interface or to an abstract class and inherit from it. Then you'll ask Guice to provide different classes to the constructors.
You need to bind your DbAccessor class twice, with a different qualifier annotation for each table. Then your classes can each inject the right qualified binding they need.

How to select JDBC / JPA implementations at run time?

I'm writing an application meant to manage a database using both JDBC and JPA for an exam. I would like the user to select once at the beginning the API to use so that all the application will use the selected API (whether it be JPA or JDBC).
For the moment I decided to use this approach:
I created an interface for each DAO class (e.g. interface UserDAO) with all needed method declarations.
I created two classes for each DAO distinguished by the API used (e.g UserDAOImplJDBC and UserDAOImplJPA). Both of them implement the interface (in our case, UserDAO).
I created a third class (e.g. UserDAOImpl) that extends the JDBC implementation class. In all my code I've been always using this class. When I wanted to switch to the JPA I just had to change in all DAO classes the extends ***ImplDAOJDBC to extends ***ImplDAOJPA.
Now, as I'm starting having many DAO classes it's starting being complicate to modify the code each time.
Is there a way to change all extends faster?
I was considering adding an option in the first screen (for example a radioGroup) to select JDBC or JPA. But yet I have no idea how to make it work without having to restructure all code. Any idea?
Use a factory to get the appropriate DAO, every time you need one:
public class UserDaoFactory {
public UserDao create() {
if (SomeSharedSingleton.getInstance().getPersistenceOption() == JDBC) {
return new UserDAOImplJDBC();
}
else {
return new UserDAOImplJPA();
}
}
}
That's a classic OO pattern.
That said, I hope you realize that what you're doing there should really never be done in a real application:
there's no reason to do the exact same thing in two different ways
the persistence model of JPA and JDBC is extremely different: JPA entities are managed by the JPA engine, so every change to JPA entities is transparently made persistent. That's not the case with JDBC, where the data you get from the database is detached. So the way to implement business logic is very different between JPA and JDBC: you typically never need to save any change when using JPA.
You got 1 and 2 right, but 3 completely wrong.
Instead of having Impl extending one of the other implementations, choose which implementation to initialize using a utility method, for example. That's assuming you don't use Dependency Injection framework such as Spring.
UserDAO dao = DBUtils.getUserDAO();
public class DBUtils {
public static boolean shouldUseJdbc() {
// Decide on some configuration what should you use
}
public static UserDAO getUserDAO() {
if (shouldUseJdbc()) {
return new UserDAOImplJDBC();
}
else {
return new UserDAOImplJPA();
}
}
}
This is still jus an examle, as your DAOs don't need to be instantiated each time, but actually should be singletons.

Can we mock a method in service while testing the service itself?

I am working on a project where I am using MyBatis annotations as persistence framework. Therefore, I have to create an interface for the 'mapper' and compose the mapper in the service like :
class XYZServiceImpl{
public XYZMapper getXYZMapper(){
return SessionUtil.getSqlSession().getMapper(XYZMapper.class)
}
}
Now while unit testing the service with Mockito, I am trying to inject a mock for the mapper. But since I am injecting mock in an instance of XYZService, how can mock a method of the service itself, in this case getXYZMapper() is what I am trying to stub. Although I have got a solution of creating the instance XYZMapper in the service and not call on demand like the above code does something like :
Class XYZServiceImpl{
XYZMapper mapper;
public void useXYZMapper(){
mapper = SessionUtil.getSqlSession().getMapper(XYZMapper.class);
}
}
But that would bring a lot of code changes (ofcourse I can refactor) but is there a way to achieve without having to make code changes?
Also what would be a 'purist' way to have a mapper instance in the class is it the method 1 that is better than method 2 in terms of performance?
EDIT : Here XYZMapper is an interface. Something like :
public interface XYZMapper{
#Select("SELECT * FROM someclass WHERE id = #{id}")
public SomeClass getSomeClass(int id);
}
EDIT : I am facing a similar situation but with a variance that I have a service that I do want to test like XYZServiceImpl. Now it has a method getXYZDetails() which has a lot of business logic handled within the service. Now if getXYZDetails looks like the following :
public XYZDetails getXYZDetails(int id){
XYZDetails details = new XYZDetails();
details.set1Details(fetchSet1Details(id));
//Perform some business logic
details.set2Details(fetchSet2Details(id));
if(details.set2Details() != null){
for(int i = 0; i < details.set2Details().size(); i++){
flushTheseDetails(i);
}
}
.
.
}
Kindly notice that fetchSet1Details(), fetchSet2Details(), flushTheseDetails are public service, public and private service respectively.
I want to know of a method that can mock/stub these methods while testing getXYZDetails() thus enabling me to
There are several options you can use.
Inject dependency
This works only for simple methods like getXYZMapper when method only returns external dependency of you object. This may require to create new XYZServiceImpl instances if for example mapper is bound to connection which is opened per request.
Encapsulate method behavior in object
Another way to achieve similar result is to use a factory or service locator
like this:
public class XYZServiceImpl {
public XYZServiceImpl(XYZMapperFactory mapperFactory) {
this.mapperFactory = mapperFactory;
}
public XYZMapper getXYZMapper() {
return mapperFactory.getMapper();
}
}
This will allow you easily substitute factory in test with implementation which returns mock mapper.
The similar approach can be used for other methods fetchSet1Details, fetchSet2Details, flushTheseDetails that is moving them to other class or classes. If the method contains complex (and may be loosely related) logic it is a good candidate to be moved in separate class. Think about what these methods do. Usually you can move some essential and unrelated part of them to other class or classes and this makes mocking them much easier.
Subclass
This is not recommended but in legacy code sometimes is very helpful as a temporary solution.
In your test subclass you class under test and override methods you need:
#Test
public void someTest() {
XYZServiceImpl sut = new XYZServiceImpl() {
public XYZMapper getXYZMapper() {
return mapperMock;
}
public Whatever fetchSet1Details() {
return whateverYouNeedInTest;
}
}
sut.invokeMethodUnderTest();
}
The only thing you may need to do is to change access modifier of private method to package-private or protected so you can override them.
Spying
This method in also discouraged but you can use mockito spies:
XYZServiceImpl realService = new XYZServiceImpl();
XYZServiceImpl spy = Mockito.spy(realService);
when(spy.fetchSet1Details()).thenReturn(whaeveryouneed);
when(spy.getXYZMapper()).thenReturn(mockMapper);
spy.methodUnderTest();
I would suggest the "purist" way of doing this is to accept an XYZMapper instance in your constructor and store it in a local field.
In production use, you can pass an e.g. SQLXYZMapper, which will interact with your database. In test use, you can pass in a mocked object that you can verify interactions with.

Categories