How do I create and use a spring boot testing utility class? - spring-boot

I want to create a utility class just for my tests that have some methods that all tests will use to reduce code duplication.
Where do I create this class and how do I import it in my tests?
Errors
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'FooTest': Unsatisfied dependency
expressed through field 'myTestUtils'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.utils.MyTestUtils' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Files
// src/test/com/example/utils/MyTestUtils.java
public class MyTestUtils {
public String foo = "bar";
}
// src/test/com/example/services/FooTest.java
import com.example.utils.TestUtils;
#SpringBootTest
public class FooTest {
// If I remove this decorator I get that this.testUtils is null
#Autowired
MyTestUtils myTestUtils
#Test
public void testFoo() throws Exception {}
Asserthat(myTestUtils.foo).equals("bar")
}
Update
I solved the problem above with annotating the myTestUtils class with #Service
This works.
// src/test/com/example/utils/MyTestUtils.java
#Service
public class MyTestUtils {
public String foo = "bar";
}

Related

How to obtain bean from context?

I have two services A and B, and A has in its pom file the dependency from B.
In service B I am creating a bean of a class named ClassB, and in service A I have a class called ClassA that receives in the constructor as parameter an instance of the ClassB from the other service.
Even I specify in the import section that is from the other service when I run both services I get the error:
Error creating bean with name 'classA' defined in file
[something/ClassA.class]: Unsatisfied dependency expressed through
constructor parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'something.something.something.something.something.ClassB' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {}
I don't know how to specify to autowire the class with the bean of the other service.
package .....;
import something.something.something.something.something.ClassB;
public class ClassA {
private ClassB classB;
#Autowired
public ClassA(ClassB classB) {
this.classB = classB;
}
//More methods not relevant
}
Thank you for your help!
Inn your #Configuration class create a a method anotated with #Bean that returns the ClassB instance named classB as below
#Configuration
public class YourConfigClass {
...
.
.
#Bean
public ClassB classB() {
return new ClassB();
}
.
.
...
}

UnsatisfiedDependencyException during test

I use psring boot 2, postgres and Jpa with hibernate.
I would like to test one of my class
#Component
public class ExportsFacade {
private SamplesService sampleService;
private SamplesRepository sampleRepository;
#Autowired
public ExportsFacade(SamplesService sampleService, SamplesRepository sampleRepository) {
this.sampleService = sampleService;
this.sampleRepository=sampleRepository;
}
...
}
I created this test
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureTestDatabase(replace=Replace.NONE)
public class ExportsFacadeTest {
#Autowired
private ExportsFacade exportsFacade;
#Test
public void export() throws IOException {
exportsFacade.generateExport();
}
}
I get this error
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'com.lcm.facade.ExportsFacadeTest':
Unsatisfied dependency expressed through field 'exportsFacade'; nested
exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'com.lcm.facade.ExportsFacade' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}

Test application cannot find autowired bean in same project

I have a jar file that is the persistence layer, ad I just want to test the DAO that are simply autowired into other service layer clasees. But I want to test without any mocking or whatever.
I think this should be pretty simple. I have this in my srs/test/java
#RunWith(SpringRunner.class)
#ComponentScan("com.xxxx")
public class ApplicationTester {
#Autowired
AplicationDocumentDao aplicationDocumentDao;
#Test
private void testAplicationDocumentDao() {
aplicationDocumentDao.allForOrg(1);
}
}
All the DAO's are in the same projust under the usual /src/main/java
When I run the mvn to just run the tests like this:
mvn -Dtest=ApplicationTester test
I get this error:
Error creating bean with name 'xxx.test.ApplicationTester': Unsatisfied dependency expressed through field 'aplicationDocumentDao';
nested exception is 0rg.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xxx.dao.AplicationDocumentDao' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Which means is can't find the Bean of course, but i would think the #ComponentScan would pick up add the Dao's.
How do I get this tester to find all my Dao's (Which are all annotated with #Componenet) and are picked up just fine in the rest for the application.
Any ideas?
** EDIT **
here is the DAO
#Repository
#Component
public class AplicationDocumentDao extends JdbcDaoSupport {
#Autowired
public void setJT(JdbcTemplate jdbcTemplate) {
setJdbcTemplate(jdbcTemplate);
}
public List<ApplicationDocumentBean> allForOrg(int orgId) {
String sql = "SELECT * FROM ApplicationDocument WHERE organizationId = ?";
return (List<ApplicationDocumentBean>) getJdbcTemplate().query(sql, new BeanPropertyRowMapper<ApplicationDocumentBean>(ApplicationDocumentBean.class), orgId);
}
}
Add annotate to your persistence layer class, for example: #Repository or #Component,like this :
#Repository
public interface OrderMapper {}

Spring Injecting implementation instead of interface

Here my class structure :
public interface CertificatService
{
}
The only one implementation
#Service
#Transactional
public class CertificatServiceImpl extends GestionCertificat implements CertificatService
{
}
And the injection :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatServiceImpl certificatService;
}
}
Injection the implementation causes injection failure :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connexionEbicsServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tess2i.service.impl.CertificatServiceImpl com.tess2i.service.impl.ConnexionEbicsServiceImpl.certificatService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.tess2i.service.impl.CertificatServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.inject.Inject()}
But if I inject the interface, it works :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatService certificatService;
}
}
But I need to inject the implementation so to benefit methods inherited from GestionCertificat
Can you help me to autowired the implementation. I understand that the real type is a proxy and not the implementation class CertificatServiceImpl as I would like. But what is the solution so ?
Thanks.
Perfect.
Just using proxy via CGLIB it is OK setting proxyTargetClass = true :
#EnableTransactionManagement(proxyTargetClass = true)
Thanks for the answer here : Spring - how to inject concrete interface implementation?

Autowiring of #Repository interface fails in concrete class

I have a concrete class implementing an interface as below:
#Service
public class BaseImpl implements Base{
#Autowired
Details details;
...
public void doSomething(){
}
}
Code for the interface:
#Service
public interface Base{
void doSomething();
}
My configuration class:
#Configuration
public class AppConfig {
#Bean(name="samplebean")
public Base getImpl(){
return new BaseImpl();
}
}
And the Details interface (which is annotated with #Repository):
#Repository
public interface Details extends CrudRepository<..., ...>{
...
}
Finally, I call the BaseImpl class as below:
#RestController
#RequestMapping(value = "...")
public class Caller{
public void foo(){
Base b = (Base) context.getBean("samplebean");
b.doSomething();
}
}
I get the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.model.Details com.pkg.BaseImpl.details; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.model.Details] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 35 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.model.Details] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 37 more
However, when I do the same auto-wiring in the Caller class (or for that matter any other class which is not implementing an interface), it seems to work fine. I'm new to Spring, so I might be missing something here.
Thanks.
You need to tell spring about the Details bean. Either declare it as a bean,
#Configuration
public class AppConfig {
#Bean(name="samplebean")
public Base getImpl(){
return new BaseImpl();
}
#Bean
public Details details() {
return new Details();
}
}
or annotate it with #Component (or some other more appropriate stereotype)
#Component
public class Details {
// ...
}
Since you are annotating your Details class with #Repository, you just need to add #ComponentScan annotation to your configuration class with the correct base package names.
#ComponentScan(basePackages = { "<yourBasePackage>" })

Resources