I wonder whether it's possible to replace all the Autowired fields with final ones and #RequiredArgsConstructor below the class declaration?
For instance, replace the following code
public class Controller {
#Autowired
private Reposiroty repository;
#Autowired
private Service service;
...
}
with something like that:
#RequiredArgsConstructor
public class Controller {
private final Reposiroty repository;
private final Service service;
...
}
Thanks in advance!
Related
I use Project Lombok for my Java projects.
My Controller looks like this:
#RestController
#AllArgsConstructor
public class UserController {
private RegisterService registerService;
private UserService userService;
private UserValidator userValidator;
private LoginService loginService;
/*
* rest of the controller
*/
}
so the controller must look like this:
#WebMvcTest(UserController.class)
public class UserControllerTest {
#MockBean
private UserRepository userRepository;
#MockBean
private RegisterService registerService;
#MockBean
private UserService userService;
#MockBean
private LoginService loginService;
#MockBean
private UserValidator UserValidator;
/*
* rest of the contoller test
*/
}
Just to make programming less code-monkey, is there anything like #AllMockArgConstructor?
Or any way, I don't always have to add all services?
If this is a stupid question, please explain me why.
Thanks in advance!
Unfortunately it cannot be done,
#MockBeans annotation target is applied only to fields and types, and not for methods, you can read more about it here.
If #MockBeans was able to support also methods then it was can be done that way:
#Getter(onMethod_={#MockBean} )
#WebMvcTest(UserController.class)
public class UserControllerTest {
...
}
I have following component:
#Component
public class ServiceManagerImpl implements ServiceManager {
private final ServiceA serviceA;
private final ServiceB serviceB;
private final String path;
#Autowired
protected ServiceManagerImpl(ServiceA serviceA, ServiceB serviceB, String path) {
this.serviceA= serviceA;
this.serviceB= serviceB;
this.path= path;
}
(...)
}
Now I want to create simple service to which I will inject above component with specific path value. This value should come from class with String constans:
#Component
public class ServiceManagerClientImpl implements ServiceManagerClient {
private ServiceManager serviceManager;
#Autowired
public ServiceManagerClientImpl(ServiceManager serviceManager) {
this.serviceManager = serviceManager;
}
}
Is it possible to dynamically inject simple path values on ServiceManagerClientImpl level (not from properties / yaml files)?
You can autowire the Environment class
import org.springframework.core.env.Environment;
#Autowired
private Environment environment;
You can read the enironment variable("path" in your case) using the below statement.
environment.getProperty("path");
I have a spring boot app that I am using with the Web Plugin.
In one class I have:
package com.test.company
#Component
#RestController
public class CompanyService {
#Autowired
private MongoTemplate mongoTemplate;
#Autowired
private Environment env;
And in another class I have:
package com.test.company
#Component
#RestController
public class CustomerSignUpService {
private static MongoTemplate mongoTemplate;
#Autowired
private Environment env;
#Autowired
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
Both classes work but if I try to inject mongo into the CusomterSignUpService class like I did in the CompanyService class, the env is injected fine, but mongo doesn't inject and I get a null pointer exception if I try to use it.
Any thoughts? Main package is com.test.
I believe your Controller might need to look like (removed static from property):
package com.test.company
#Component
#RestController
public class CustomerSignUpService {
#Autowired
private MongoTemplate mongoTemplate;
#Autowired
private Environment env;
...
...
}
You can use #Autowired both in the attribute and in the setter, but your attribute must be an instance variable, not a static one.
So do this and your code should run fine:
package com.test.company
#Component
#RestController
public class CustomerSignUpService {
private MongoTemplate mongoTemplate;
#Autowired
private Environment env;
#Autowired
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
Note that the static reserved word was taken from your attribute declaration.
Remove static from the property and try it without it
package com.test.company
#Component
#RestController
public class CustomerSignUpService {
#Autowired
private MongoTemplate mongoTemplate;
#Autowired
private Environment env;
...
...
}
Is it possible to just ignore/mock any injected dependencies inside a MockedBean?
Example:
#Service
public class MyService {
#Autowired
private MailerService mailer;
public void test1() {
//does not use mailer
}
public void test2() {
//...
mailer.send();
}
}
#Service
public class MailerService {
//I want these to be automatically mocked without explicit declaration
#Autowired
private JavaMailSender sender;
#Autowired
private SomeMoreService more;
//also these should be mocked without having to provide properties
#Value("${host}") private String host;
#Value("${user}") private String user;
#Value("${pass}") private String pass;
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class MyServiceTest {
#Autowird
private MyService myservice;
#MockBean
private MailserService mailer;
#Test
public void test1() {
myservice.test1();
}
}
I could use #MockBean to sort out mailer injection dependency. But any service inside the mocked bean would also have to be explicitly mocked.
Question: is it possible to mock a service "away". Means, just mock the bean and don't care what's inside the #MockedBean (or automatically also mock anything inside #MockedBean)?
As for me the best way to inject mocks is to use MockitoJUnitRunner
#RunWith(MockitoJUnitRunner.class)
public class MocksTests {
#InjectMocks
private ParentService parent;
#Mock
private InnerService inner; // this will be injected into parent
//your tests
}
#Component
public class IServiceCollection {
#Resource
private IService service1;
#Resource
private IService service2;
#Resource
private IService service3;
#Resource
private IService service4;
#Resource
private IService service5;
public List<IService> getAllServices(){
List<IService> iServiceList = new ArrayList<IService>();
iServiceList.add(service1);
iServiceList.add(service2);
return iServiceList;
}
}
in IServiceCollection I will refer lots of IService beans like service1, servvice2, etc. I wanna get all of the service beans in method getAllServices().
How can I add all the services to the list automatically, not like the code above?
You have a few options:
.1. If you inject in a map this way:
#Component
public class IServiceCollection {
#Autowired
private Map<String, IService> services;
that would inject in all implementations of IService with the key of the map being the bean name
.2. You can inject in a list this way:
#Component
public class IServiceCollection {
#Autowired
private List<IService> services;
again you would have a list of IService instances.