I am using Quarkus for a little project and I got stuck in unit testing my classes using the tools that Quarkus offers.
The problem is, I used the following approach to mock som classes:
https://quarkus.io/guides/getting-started-testing#mock-support
Mocking my Dao or Service class would be a nice way in my opinion.
However Mocking my classes leads to the effect that when I inject my Service/Dao class that has to be tested, the container for sure injects the Mock implementation.
Is there a way to prevent that and use the real implementation class?
#ApplicationScoped
public class ExpenseDaoImpl implements ExpenseDao {
}
#Mock
#ApplicationScoped
public class ExpenseDaoMock implements ExpenseDao {
}
#QuarkusTest
class ExpenseDaoTest {
#Inject
private ExpenseDao expenseDao; //injects the mocked implementation
}
Related
Is it fine to have a #Service annotated class calling another #Service annotated class? Or it is a bad practice?
Eg.:
#Service
public class MyService {
// ...
#Autowired
private MyOtherService myOtherService;
// ...
}
It is not any restriction calling a service from another one. Unless you make circular dependency between services.
Circular dependency : https://en.wikipedia.org/wiki/Circular_dependency
Circular dependency in spring : https://www.baeldung.com/circular-dependencies-in-spring
Its good practice since utility class are being ignored these days, approach getting motivated by horizontal scaling... Surely services got to interact with other.
No need to worry, its like one service manager needs services of another manager.
just only one should be dependent on other, not both.
#Service
public class MyService {
// ...
#Autowired
private MyOtherService myOtherService = new MyOtherService();
// ...}
Try this. It is worked for me. You can use the methods of a service in many sevice.
I have an spring boot app that has a mongo repository and is using spring data to connect to it. This means there's an "entity" class and then a "repository" class.
However, to actually use the repository I need spring to #Autowire my repo to a variable inside another class (we'll call it X) that might want to use it. But if the X class is itself not a spring bean, it's just a regular pojo created by "new X" somewhere then it can't make use of Autowiring and therefore cant use the repo.
This seems like a show stopper... No one could ever make use of a repo outside of some very specific situations like calling the repo directly from your RestController or whatever without any intervening logic. Yet I am sure people are using this.
So my question is how to structure code so that it can be used? Do I need to do a bunch of processing and then return back up to the controller to interact with the databases? Is there a way to create some kind of other "intermediate helper bean" to mediate the connection? What should that look like?
disclaimer: I am fairly new to spring
Perhaps I can post some excerpts that can clarify your situation.
//nothing spring specific
public class MyPojo {
//properties
}
in a different package:
#Repository
public class MyRepositoryImpl implements MyRepository {
//CRUD implementation or whatever
}
in a different package:
#Service
public class MyServiceImpl implements MyService {
#Autowired //constructor-injection
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
private final MyRepository myRepository;
public void myBusinessLogic() {
MyPojo pojo = new MyPojo(); //not dependent on Spring
myRepository.doSomething();
//place calls to X here as needed
}
}
And finally:
#Controller
public class MyController {
#Autowired
public MyController(MyService myService) {
this.myService = myService;
}
private final MyService myService;
#GetMapping("/myPage")
public String doIt() {
myService.myBusinessLogic();
return "myPage";
}
}
Where MyRepository and MyService are interfaces that would contain the contract for their respective implementations.
Single Responsibility Principle
A major point to note is that your POJO isn't going to "use the repo" as you mention in your question. It represents an entity and shouldn't care about any specific repository. And this seems related to your issue - a POJO shouldn't be making calls to a repository (your "X" class in this case). Seems like the design should be revisited if that is the case.
As you say, you can only autowire fields in objects that themselves are autowired. This is inherent to bean injection. You should annotate X with for instance #Component and inject it where you need it.
I am trying to create my first integration test, inspiring myself from the jhipster project.
In my setup, i use that kind of code:
CampaignController campaignController = new CampaignController();
ReflectionTestUtils.setField(campaignController, "securityService", securityService);
ReflectionTestUtils.setField(campaignController, "campaignService", campaignService);
ReflectionTestUtils.setField(campaignController, "messageService", messageService);
MockMvc restMvcCampaignController = MockMvcBuilders.standaloneSetup(campaignController).setMessageConverters(TestUtil.getCustomJsonMessageConverter()).build();
RestAssuredMockMvc.mockMvc(restMvcCampaignController);
Services are autowired classes.
I would like to know if "ReflectionTestUtils.setField" is a good practice or if there is anything else better I could use ?
Thank you
It's not a good practice. Instead of making it impossible to set the dependencies (other then by reflection), inject the dependencies via a constructor. For example
#Controller
public class Controller {
private CampaignService campaignService;
#Autowired
public Controller(CampaignService campaignService, MessageService messageService) {
//bind fields
}
}
Now you can instantiate the controller easily from the test.
I am a big fan of Play, and I use it in almost any project of mine nowadays. As one of my projects got bigger, though, I decided to include a DI solution. After a brief consideration between Spring and Guice, I stopped on Guice and added the Guice module for Play (http://www.playframework.com/modules/guice-1.0/home).
The problem with it, seems to be the fact that injection works for static fields only. This means that I will have to do stuff like:
#InjectSupport
public class MyService {
#Inject
static MyBean myBean;
}
from (http://java.dzone.com/articles/dependency-injection-play)
which scares me a bit, especially when it comes to testing. I mean, it is true that most of the DI solutions always try to inject singletons, for instance Spring creates a single instance of every bean and injects it, which is kind of the same at the end, but still. Should I have these concerns?
You definitely can perform Guice injection with Play.
You should not use the old Guice module (version 1.0). The tutorial you referred to is also using the old Guice, and old Play (version 1.2!)
Please take a look of the new Guice module (version 3.0) & Play (version 2.1.1)
http://www.playframework.com/documentation/2.1.1/JavaInjection
When you inject to an instance variable, you need to create controller dynamically
In your route file:
GET / #controllers.Application.index()
In your Global.java, you need to override getControllerInstance:
#Override
public <A> A getControllerInstance(Class<A> controllerClass) throws Exception {
return INJECTOR.getInstance(controllerClass);
}
In Play 1, you can easily combine normal Guice singletons with statically injected controller fields, the trick is getting the annotation imports correct.
In your play controllers, jobs & test classes that need static injection use the JSR330 annotation versions:
import javax.inject.Inject;
public class Application extends Controller {
#Inject private static MyService myService;
....
}
and for other classes that need #InjectSupport use JSR330/module imports:
import play.modules.guice.InjectSupport;
import javax.inject.Inject;
#InjectSupport
public class AnotherClass {
#Inject private static MyService myService;
}
For the actual (non-static) services instantiated by Guice library, you need to use the Guice annotation versions (note the com.google.inject package):
import com.google.inject.Inject;
import com.google.inject.Singleton;
#Singleton
public class MyService {
#Inject private AnotherService anotherService; // note non-static injection
}
You'll also need an empty Module to kick things off:
import com.google.inject.AbstractModule;
public class MainModule extends AbstractModule {
#Override
protected void configure() {}
}
This should also work for Guice classes created in other ways apart from #Singleton, such as #Provides, although I haven't tried this yet.
Which one is the best way of injecting my dependencies? Why?
What is the difference between the two?
public abstract class Service {
private IConfig config;
#Inject
public Service(IConfog config) {
this.config = config
}
}
Or
public abstract class Service {
#Inject private IConfig config;
#Inject
public Service() {
}
}
Constructor injection (1st) is preferred over setter injection given that it makes it easier to support "immutable" entities or entities whose behaviour is well defined and non-modifiable after construction. Constructor vs Setter inject
For me the rule of thumb is to first prefer constructor injection and jump off to setter injection if constructor inject requires me to bend my back i.e. when working with legacy code with "OOP getter and setter" methods.
EDIT: I'm assuming you are trying to decide between "constructor" and "setter" constructor. But it also seems that you are using abstract classes which can't be instantiated. Maybe you have something else in mind?
First of all, I do not put injection-related annotations in abstract classes - in my opinion there is no sense in deciding how something should be instantiated if it actually cannot be instantiated (of course that's only my opinion with which others may agree or not).
Usually I do it in the following way:
public abstract class AbstractService {
private IConfig config;
public AbstractService(IConfog config) {
this.config = config
}
}
public class Service extends AbstractService {
#Inject
public Service(IConfig config) {
super(config);
}
}
Now, you can use both classes with and without dependency injection (construct it by hand, passing all required references). Also you can be sure that Service is instantiated in the appropriate state every time.
The main goal of dependency injection is to make unit testing easy by allowing to do
Service serviceToTest = new Service(mockConfig);
or
Service serviceToTest = new Service();
serviceToTest.setConfig(mockConfig);
The second way of injecting dependencies makes it impossible to do the abover. You can only test it by letting Guice create the service and inject a mock dependency, or by using reflection to set the mock dependency.