Getting "At least one JPA metamodel must be present" with #WebMvcTest - java

I'm fairly new to Spring, trying to do some basic integration tests for a #Controller.
#RunWith(SpringRunner.class)
#WebMvcTest(DemoController.class)
public class DemoControllerIntegrationTests {
#Autowired
private MockMvc mvc;
#MockBean
private DemoService demoService;
#Test
public void index_shouldBeSuccessful() throws Exception {
mvc.perform(get("/home").accept(MediaType.TEXT_HTML)).andExpect(status().isOk());
}
}
but I'm getting
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: At least one JPA metamodel must be present!
Caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!
Unlike most people posting this error, I don't want to use JPA for this. Am I trying to use #WebMvcTest incorrectly? How can I track down the Spring magic that's inviting JPA to this party?

Remove any #EnableJpaRepositories or #EntityScan from your SpringBootApplication class instead do this:
package com.tdk;
#SpringBootApplication
#Import({ApplicationConfig.class })
public class TdkApplication {
public static void main(String[] args) {
SpringApplication.run(TdkApplication.class, args);
}
}
And put it in a separate config class:
package com.tdk.config;
#Configuration
#EnableJpaRepositories(basePackages = "com.tdk.repositories")
#EntityScan(basePackages = "com.tdk.domain")
#EnableTransactionManagement
public class ApplicationConfig {
}
And here the tests:
#RunWith(SpringRunner.class)
#WebAppConfiguration
#WebMvcTest
public class MockMvcTests {
}

I had the same problem. #WebMvcTest looks for a class annotated with #SpringBootApplication (in the same directory or higher up in your app structure if it doesn't find one). You can read how this works # https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests.
If your class annotated with #SpringBootApplication also has #EntityScan /#EnableJpaRepositories this error occurs. Because you have these annotations with #SpringBootApplication and you are mocking the service ( so actually not using any JPA ). I found a workaround which may not be the prettiest, but works for me.
Place this class in your test directory ( the root ). #WebMvcTest will find this class before your actual Application class. In this class you don't have to add #EnableJpaRepositories/#EntityScan.
#SpringBootApplication(scanBasePackageClasses = {
xxx.service.PackageMarker.class,
xxx.web.PackageMarker.class
})
public class Application {
}
And your test will look the same.
#RunWith(SpringRunner.class)
#WebMvcTest
#WithMockUser
public class ControllerIT {
#Autowired
private MockMvc mockMvc;
#MockBean
private Service service;
#Test
public void testName() throws Exception {
// when(service.xxx(any(xxx.class))).thenReturn(xxx);
// mockMvc.perform(post("/api/xxx")...
// some assertions
}
}
Hope this helps!

Alternatively, you can define a custom configuration class inside your test case, including only the controller (plus its dependencies), to force Spring to use this context.
Please note, you'll still have access to MockMvc and other goodness in your test case, if it's WebMvcTest annotated.
#RunWith(SpringRunner.class)
#WebMvcTest(DemoController.class)
public class DemoControllerIntegrationTests {
#Autowired
private MockMvc mvc;
#MockBean
private DemoService demoService;
#Test
public void index_shouldBeSuccessful() throws Exception {
mvc.perform(get("/home").accept(MediaType.TEXT_HTML)).andExpect(status().isOk());
}
#Configuration
#ComponentScan(basePackageClasses = { DemoController.class })
public static class TestConf {}

Add #MockBean(JpaMetamodelMappingContext.class) to above of class DemoControllerIntegrationTests:
#RunWith(SpringRunner.class)
#WebMvcTest(DemoController.class)
#MockBean(JpaMetamodelMappingContext.class)
public class DemoControllerIntegrationTests {
...
}
Because you have not used a database in your test, Spring throws this exception. By mocking JpaMetamodelMappingContext class you will bypass the needed metamodel.

If anyone uses Spring boot and don't want to remove #EntityScan and #EnableJpaRepositories you can remove #WebMvcTest annotation from your test class and add the following instead:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
public class DemoControllerIntegrationTests {
#Autowired
private MockMvc mvc;
//...
}
and you will be able to autowire MockMvc and use it.

Related

Spring: Service Class with #Service annotation gets "required bean of type 'abcService' could not be found"

I have a spring batch application in which the writer has an #Autowired field (it is a service class). When running tests for the writer step, I am met with the error:
Field batchTrackingService in com.ally.cr.miscinfo.batch.writer.AdvantageClientItemWriter required a bean of type 'com.test.miscinfo.service.TestService' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.test.miscinfo.service.batchTrackingService ' in your configuration.
I've looked at a few answers to related questions, and most of them are caused by the fact that the class being injected has not been annotated with #Component, #Service, #Repository, etc. However mine is. I also read questions where the supposed solution was to add the #ComponentScan() annotation to the Main class of my application. After trying this, it gave the same error. Can someone please help me? Any help is appreciated.
Here are the relevant classes:
Main class:
#SpringBootApplication
#EnableBatchProcessing
#EnableJpaRepositories("com.test.miscinfo.repository")
#EntityScan("com.test.miscinfo.entity")
#ComponentScan("com.test.miscinfo.service")
public class MiscInfoServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MiscInfoServiceApplication.class, args);
}
}
Writer class:
#Slf4j
#Component
#AllArgsConstructor
#NoArgsConstructor
public class AdvantageClientItemWriter implements ItemWriter<MiscInfo> {
#Autowired private AdvantageClientConfig advantageClientConfig;
#Autowired WebClient advantageClientWebClient;
#Autowired private BatchTrackingService batchTrackingService;
#Override
public void write(List<? extends MiscInfo> miscInfos) throws Exception {
/* some call to a method in the injected service */
}
}
Service class:
#AllArgsConstructor
#NoArgsConstructor
#Slf4j
#Transactional
#Service
public class BatchTrackingService {
public void someMethod() {}
}
Please let me know if I am missing relevant info.
EDIT:
Adding test method:
#ExtendWith(SpringExtension.class)
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#EnableConfigurationProperties(value = AdvantageClientConfig.class)
#SpringBootTest
#ActiveProfiles("test")
#ContextConfiguration(classes = { AdvantageClientItemWriter.class })
public class AdvantageClientItemWriterTest {
#MockBean RestTemplate advantageClientRestTemplate;
#MockBean WebClient advantageWebClient;
WebClient.RequestBodyUriSpec requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class);
WebClient.RequestBodySpec requestBodySpec = mock(WebClient.RequestBodySpec.class);
WebClient.ResponseSpec responseSpec = mock(WebClient.ResponseSpec.class);
WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class);
#Autowired AdvantageClientConfig advantageClientConfig;
#Autowired AdvantageClientItemWriter advantageClientItemWriter;
ArgumentCaptor<String> uriCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<MediaType> mediaTypeCaptor= ArgumentCaptor.forClass(MediaType.class);
ArgumentCaptor<String> headerNameCaptor= ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> headerValueCaptor= ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> bodyCaptor= ArgumentCaptor.forClass(String.class);
private MemoryAppender memoryAppender;
#BeforeEach
public void init(){
Logger logger = (Logger) LoggerFactory.getLogger("com.test");
memoryAppender = new MemoryAppender();
memoryAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory());
logger.setLevel(Level.DEBUG);
logger.addAppender(memoryAppender);
memoryAppender.start();
}
#Test
public void successfulAdvantageClientWrite() throws Exception {
setupMockReturns();
when(responseSpec.toBodilessEntity()).thenReturn(Mono.just(new ResponseEntity(null, HttpStatus.OK)));
List<MiscInfo> miscInfos = new ArrayList<>();
final MiscInfo miscInfo = createMiscInfo1();
miscInfos.add(miscInfo);
advantageClientItemWriter.write(miscInfos);
Assertions.assertEquals(advantageClientConfig.getEndpoint(), uriCaptor.getValue());
Assertions.assertEquals(MediaType.APPLICATION_JSON, mediaTypeCaptor.getValue());
Assertions.assertEquals( advantageClientConfig.getHeaderName(), headerNameCaptor.getValue());
Assertions.assertEquals(advantageClientConfig.getApiKey(), headerValueCaptor.getValue());
Assertions.assertEquals(new ObjectMapper().writer().withDefaultPrettyPrinter().writeValueAsString(miscInfos), bodyCaptor.getValue());
assertThat(memoryAppender.search("Write to Advantage status: ", Level.DEBUG).size()).isEqualTo(1);
}
}
This error means that Spring is trying to autowire of bean of type BatchTrackingService in your AdvantageClientItemWriter but it could not find one in the application context. In other words, your test context does not contain a bean definition of type BatchTrackingService, which could be due to one of the following causes:
Either the configuration class that defines that bean is not imported in the test class (in #ContextConfiguration(classes = { AdvantageClientItemWriter.class })
or the class of that bean is not in the package that is scanned by Spring (Boot).
Make sure that:
the class public class BatchTrackingService {} is defined in the package referenced in #ComponentScan("com.test.miscinfo.service")
the #ContextConfiguration annotation imports the class of that bean (something like #ContextConfiguration(classes = { AdvantageClientItemWriter.class, BatchTrackingService.class }), or that it imports a configuration class which defines an instance of that bean.

Unable to find a #SpringBootConfiguration

I want to create a JUnit test for this private method:
#Component
public class ReportingProcessor {
#EventListener
private void collectEnvironmentData(ContextRefreshedEvent event) {
}
}
I tried this:
#ContextConfiguration
#SpringBootTest
public class ReportingTest {
#Autowired
ReportingProcessor reportingProcessor;
#Test
public void reportingTest() throws Exception {
ContextRefreshedEvent contextRefreshedEvent = PowerMockito.mock(ContextRefreshedEvent.class);
Whitebox.invokeMethod(reportingProcessor, "collectEnvironmentData", contextRefreshedEvent);
}
}
When I run the code I get:
java.lang.IllegalStateException: Unable to find a #SpringBootConfiguration, you need to use #ContextConfiguration or #SpringBootTest(classes=...) with your test
Do you know ho I can fix this issue?
If you don't have any class annotated with #SpringBootApplication and the known main() method, you need to target your component class on the #SpringBootTest annotation.
Usually I do this when I'm building libraries and for some specific scenario I need to have the spring context to unit test them.
Just add this to your code:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = ReportingProcessor.class)
public class ReportingTest {
...
Just did it and the test is running.
Edit: Don't know what are you trying to test exactly, just wanted to show how can you fix the error you are getting.
You should use the #RunWith with your #SpringBootTest:
#RunWith(SpringRunner.class)
#SpringBootTest
public class ReportingTest {
#Autowired
ReportingProcessor reportingProcessor;
#Test
public void reportingTest() throws Exception {
ContextRefreshedEvent contextRefreshedEvent = PowerMockito.mock(ContextRefreshedEvent.class);
Whitebox.invokeMethod(reportingProcessor, "collectEnvironmentData", contextRefreshedEvent);
}
}

How to integrate Spring Boot, Cucumber and Mockito?

There are ways online to integrate Cucumber with Spring Boot. But I cannot find how to do so with Mockito also. If I use the Cucumber runner and annotate the steps file with ContextConfiguration and SpringBootTest, the container injects the Autowired dependencies and its all fine. The problem is that dependencies annotated with Mock, MockBean and InjectMocks dont work. Anyone knows why it doesnt work and how to make it work?
EDIT: It is possible to instantiate the bean with mock(Bean.class), instead of using the Mock annotation. But what about features like MockBean and InjectMocks?
Runner
#RunWith(Cucumber.class)
#CucumberOptions(plugin = {"pretty", "html:build/cucumber_report/"},
features = "classpath:cucumber/",
glue = {"com.whatever"},
monochrome = true,
dryRun = false)
public class CucumberTest {
}
Steps
#ContextConfiguration
#SpringBootTest
public class CucumberSteps
{
#Autowired
private Bean bean;
#InjectMocks //doesnt work
private AnotherBean anotherBean;
#MockBean //doesnt work with #Mock also
MockedBean mockedBean;
#Given("^Statement$")
public void statement() throws Throwable {
MockitoAnnotations.initMocks(this); //doesnt work with or without this line
Mockito.when(mockedBean.findByField("value"))
.thenReturn(Arrays.asList());
}
//Given-When-Then
}
Runner :
#CucumberOptions(plugin = {"pretty"},
glue = {"com.cucumber.test"},
features = "x/y/resources")
public class CucumberTest {
}
Here we will create a class with #SpringBootTest, #RunWith(SpringRunner.class) to start load beans into spring context. Now will mock the spring beans whatever we want to mack at here
#RunWith(SpringRunner.class)
#SpringBootTest
public class SpringTest {
#MockBean
private Mockedbean mockedbean;
}
Now, we need to extend the SpringBootTest annotated testclass to CucumberSteps class, then autowire the mocked bean at here, will get the instance of mocked bean(Mockedbean). We can do autowire and get instance of other spring boot beans also(TestBean)
public class CucumberSteps extends SpringTest {
#Autowired
private Mockedbean mockedbean;
#Autowired
private TestBean testBean;
}

How can I use #WebMvcTest for a Controller that uses an autowired ConversionService?

In a Spring Boot application, I have two POJOs, Foo and Bar, and a BarToFooConverter, which looks like:
#Component
public class BarToFooConverter implements Converter<Bar, Foo> {
#Override
public Foo convert(Bar bar) {
return new Foo(bar.getBar());
}
}
I also have a controller which makes use of the converter:
#RestController("test")
public class TestController {
#Autowired
private ConversionService conversionService;
#RequestMapping(method = RequestMethod.PUT)
#ResponseBody
public Foo put(#RequestBody Bar bar) {
return conversionService.convert(bar, Foo.class);
}
}
I'd like to test this controller with #WebMvcTest, something like:
#WebMvcTest
#RunWith(SpringRunner.class)
public class TestControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void test() throws Exception {
mockMvc.perform(
put("/test")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"bar\":\"test\"}"))
.andExpect(status().isOk());
}
}
but when I run this, I find that my BarToFooConverter was not registered with the ConversionService:
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.example.demo.web.Bar] to type [com.example.demo.web.Foo]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:324)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:206)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:187)
at com.example.demo.web.TestController.put(TestController.java:15)
This seems to make sense, because, according to the Javadoc:
Using this annotation will disable full auto-configuration and instead apply only configuration relevant to MVC tests (i.e. #Controller, #ControllerAdvice, #JsonComponent Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not #Component, #Service or #Repository beans).
However, the reference guide differs slightly, saying that #WebMvcTest does include Converters:
#WebMvcTest auto-configures the Spring MVC infrastructure and limits scanned beans to #Controller, #ControllerAdvice, #JsonComponent, Converter, GenericConverter, Filter, WebMvcConfigurer, and HandlerMethodArgumentResolver. Regular #Component beans are not scanned when using this annotation.
It seems that the reference guide is incorrect here - or am I registering my Converter incorrectly?
I have also tried mocking the ConversionService in my test with:
#WebMvcTest
#RunWith(SpringRunner.class)
public class TestControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private ConversionService conversionService;
#Test
public void test() throws Exception {
when(conversionService.convert(any(Bar.class), eq(Foo.class))).thenReturn(new Foo("test"));
mockMvc.perform(
put("/test")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"bar\":\"test\"}"))
.andExpect(status().isOk());
}
}
but now Spring complains that my mock ConversionService is overriding the default one:
Caused by: java.lang.IllegalStateException: #Bean method WebMvcConfigurationSupport.mvcConversionService called as a bean reference for type [org.springframework.format.support.FormattingConversionService] but overridden by non-compatible bean instance of type [org.springframework.core.convert.ConversionService$$EnhancerByMockitoWithCGLIB$$da4e303a]. Overriding bean of same name declared in: null
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.obtainBeanInstanceFromFactory(ConfigurationClassEnhancer.java:402)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
...
Ideally I'd like to use my original approach, with the real Converter in my test rather than mocking the ConversionService, but with #WebMvcTest to limit the scope of the components that are started, so I also tried using an includeFilter in the #WebMvcTest annotation:
#WebMvcTest(includeFilters = #ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.example.demo.web.Bar*"))
but it still fails with the original 'No converter found capable of converting...' error message.
This feels like something that must be quite a common requirement - what am I missing?
You can register your converter manually in #Before annotated method. All you have to do is to inject GenericConversionService and call addConverter(new BarToFooConverter()) to make the converter resolvable. In this case you can get rid of mocking part. Your test could look like this:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#WebMvcTest
#RunWith(SpringRunner.class)
public class TestControllerTest {
#Autowired
private MockMvc mockMvc;
#Autowired
private GenericConversionService conversionService;
#Before
public void setup() {
conversionService.addConverter(new BarToFooConverter());
}
#Test
public void test() throws Exception {
mockMvc.perform(
put("/test")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"bar\":\"test\"}"))
.andExpect(status().isOk());
}
}
Alternative solution: Spring Boot since version 1.4.0 provides a collection of test-related auto-configurations and one of these auto-configurations is #AutoConfigureMockMvc that configures MockMvc component that works fine with injected converter components.

How to write JUnit test with Spring Autowire?

Here are the files that I use:
component.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<context:component-scan
base-package="controllers,services,dao,org.springframework.jndi" />
</beans>
ServiceImpl.java
#org.springframework.stereotype.Service
public class ServiceImpl implements MyService {
#Autowired
private MyDAO myDAO;
public void getData() {...}
}
ServiceImplTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath*:conf/components.xml")
public class ServiceImplTest{
#Test
public void testMyFunction() {...}
}
Error:
16:22:48.753 [main] ERROR o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener#2092dcdb] to prepare test instance [services.ServiceImplTest#9e1be92]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'services.ServiceImplTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private services.ServiceImpl services.ServiceImplTest.publishedServiceImpl; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [services.ServiceImpl] 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.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) ~[spring-beans.jar:3.1.2.RELEASE]
Make sure you have imported the correct package. If I remeber correctly there are two different packages for Autowiring. Should be :org.springframework.beans.factory.annotation.Autowired;
Also this looks wierd to me :
#ContextConfiguration("classpath*:conf/components.xml")
Here is an example that works fine for me :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/applicationContext_mock.xml" })
public class OwnerIntegrationTest {
#Autowired
OwnerService ownerService;
#Before
public void setup() {
ownerService.cleanList();
}
#Test
public void testOwners() {
Owner owner = new Owner("Bengt", "Karlsson", "Ankavägen 3");
owner = ownerService.createOwner(owner);
assertEquals("Check firstName : ", "Bengt", owner.getFirstName());
assertTrue("Check that Id exist: ", owner.getId() > 0);
owner.setLastName("Larsson");
ownerService.updateOwner(owner);
owner = ownerService.getOwner(owner.getId());
assertEquals("Name is changed", "Larsson", owner.getLastName());
}
I've done it with two annotations for test class: #RunWith(SpringRunner.class) and #SpringBootTest.
Example:
#RunWith(SpringRunner.class )
#SpringBootTest
public class ProtocolTransactionServiceTest {
#Autowired
private ProtocolTransactionService protocolTransactionService;
}
#SpringBootTest loads the whole context, which was OK in my case.
A JUnit4 test with Autowired and bean mocking (Mockito):
// JUnit starts with spring context
#RunWith(SpringRunner.class)
// spring loads context configuration from AppConfig class
#ContextConfiguration(classes = AppConfig.class)
// overriding some properties with test values if you need
#TestPropertySource(properties = {
"spring.someConfigValue=your-test-value",
})
public class PersonServiceTest {
#MockBean
private PersonRepository repository;
#Autowired
private PersonService personService; // uses PersonRepository
#Test
public void testSomething() {
// using Mockito
when(repository.findByName(any())).thenReturn(Collection.emptyList());
Person person = new Person();
person.setName(null);
// when
boolean found = personService.checkSomething(person);
// then
assertTrue(found, "Something is wrong");
}
}
For Spring 5.x and JUnit 5, writing unit tests is quite different.
We have to use #ExtendWith to register Spring extensions (SpringExtension). This brings Spring into play which activates part of the application context (instantiates and manages beans from selected configuration classes).
Note that this is different from the effect of #SpringBootTest which loads the full application context (and IMHO cannot be considered a unit test).
For example, let's create a configuration class FooConfig which produces a bean named foo1:
#Configuration
public class FooConfig
{
#Bean
public String foo1() { return "Foo1"; }
}
Now, let's write a JUnit 5 test case which injects foo1:
import static org.junit.jupiter.api.Assertions.*;
// ... more imports ...
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {
helloworld.config.FooConfig.class,
})
class FooTests
{
#BeforeAll
static void setUpBeforeClass() throws Exception {}
#AfterAll
static void tearDownAfterClass() throws Exception {}
#BeforeEach
void setUp() throws Exception {}
#AfterEach
void tearDown() throws Exception {}
#Autowired
private String foo1;
#Test
void test()
{
assertNotNull(foo1);
System.err.println(foo1);
}
}
In Spring 2.1.5 at least, the XML file can be conveniently replaced by annotations.
Piggy backing on #Sembrano's answer, I have this. "Look ma, no XML".
It appears I to had list all the classes I need #Autowired in the #ComponentScan
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(
basePackageClasses = {
OwnerService.class
})
#EnableAutoConfiguration
public class OwnerIntegrationTest {
#Autowired
OwnerService ownerService;
#Test
public void testOwnerService() {
Assert.assertNotNull(ownerService);
}
}
I think somewhere in your codebase are you #Autowiring the concrete class ServiceImpl where you should be autowiring it's interface (presumably MyService).
You should make another XML-spring configuration file in your test resource folder or just copy the old one, it looks fine, but if you're trying to start a web context for testing a micro service, just put the following code as your master test class and inherits from that:
#WebAppConfiguration
#RunWith(SpringRunner.class)
#ContextConfiguration(locations = "classpath*:spring-test-config.xml")
public abstract class AbstractRestTest {
#Autowired
private WebApplicationContext wac;
}
You can use #Import annotation. It's more readable and shorter than using the #ComponentScan annotation.
import org.springframework.context.annotation.Import;
#Import(value = {MyService.class, MyInjectedService.class})
public class JUnitTest {
#Autowired
private MyService service;
// ...
}

Categories

Resources