I have the following test code:
package soundSystem;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class )
#ContextConfiguration(classes = CDPlayerConfig.class)
public class SonyCDPlayerTest {
#Autowired
private ICompactDisk cd;
#Test
public void cdShouldNotBeNull() {
assertNotNull(cd);
}
}
This is a maven project, the problem is the exact same code would run in eclipse, but not in intellij.
I just can't find a way to resolve #RunWith
The #RunWith annotation has been replaced with #ExtendWith in JUnit 5.0 and above (which the latest spring version is now using).
Example:
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = { SpringTestConfiguration.class })
public class GreetingsSpringTest {
// ...
}
Quoted from Baeldung:
Note that SpringExtension.class is provided by Spring 5 and integrates
the Spring TestContext Framework into JUnit 5.
Ref: https://www.baeldung.com/junit-5-runwith
Simple: your IDE is not configured to for unit testing.
In other words: you are missing all the JUnit related classes. You can see that all those JUnit imports are underlined; as IntelliJ simply doesn't know about the JARs that contain the corresponding classes.
See here on how to fix that.
Related
I have created a basic Rest API with a Controller, Service and Repository layer. I am now trying to write a unit test for the Service layer method that finds product by the product id. However, when I run the test it throws a NullPointerException in the line where I am trying to mock the repository findById() method.
The getProductById() method in the service layer is as follows:
public Product getProductById(String id){ return productRepository.findById(id).orElse(null); }
My test class for the service layer:
package com.product.Services;
import com.product.Entities.Product;
import com.product.Repositories.ProductRepository;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
#RunWith(MockitoJUnitRunner.class)
class ProductServiceTest {
#InjectMocks
ProductService productService;
#Mock
ProductRepository productRepository;
#Test
void getProductById() throws Exception {
Product product = new Product();
product.setId("001");
product.setName("TV");
product.setPrice(999.99);
when(productRepository.findById("001").orElse(null)).thenReturn(product);
assertEquals(product,productService.getProductById("001"));
}
}
Attaching a picture of what the debugger shows:
The problem is that 2 different versions of JUnit are used here:
org.junit.jupiter.api.Test is from JUnit5, while
org.junit.runner.RunWith is from JUnit4.
RunWith does not exist anymore in JUnit5.
In this specific case, I would use JUnit4 - i.e. use the annotation org.junit.Test (instead of org.junit.jupiter.api.Test) to annotate your test.
How to use Mockito with JUnit5 provides other valid solutions.
JUnit 5 uses #ExtendWith(SpringExtension.class) annotation, can you change #RunWith annotation and try again?
You should mock the findById call, not the expression chained with orElse:
when(productRepository.findById("001")).thenReturn(product);
I'm working on a legacy project that have no tests. We want to add integration tests for our services.
The services communicates with other services and with the database as well.
I could handle to run junit tests so I can mock service calls and database calls to return whatever I want but I'm wondering if it's possible to run an actual integration test where it communicate with the actual dev database and with the other services in the project as well.
The beans are defined in xml files with some placeholders on it.
I'm looking for a direction on what to look for and if it is possible at all on this spring version.
Thanks!
To configure your test can you make first class SwitchCase and extend this in test class.
import java.util.Random;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = Application.class)
public class SwitchCase{
*** here you can have tour variables and do #Autowired in yours service
}
public class YoursTestClass extends SwitchCase{
#Test
public void save() throws Exception {
}
}
To do mocks you can use Mockito.
#WebMvcTest
#AutoConfigureMockMvc
public class YouClass {
#Autowired
MockMvc mock
MockHttpServelet request = MockMvcRequestBuilders
.post("http/....")
.contentTupe(**pass yout content type **);
mock.perform(request)
.andExpect(MockMvcResultMatchers.status().isCreated())
.andExpect(MockMvcResultMatchers.jsonPath("id").value(7)
}
It is just an example to guide, but it would be good to take a look at the mockito documentation
I have a Spring Boot app which contains a Spring Data Jpa repository. I need to run a unit (or component?) test around this repository. I do not have a lot of experience with Spring Data Jpa.
Here's my test. It's trivially simple, and I cannot get it to pass.
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import static org.junit.Assert.assertNotNull;
#DataJpaTest
public class FooRepositoryTest {
#Autowired
private FooRepository fooRepo;
#Test
public void notNull(){
assertNotNull(fooRepo);
}
}
Here's the other relevant source code.
import com.fedex.dockmaintenancetool.webservice.types.Foo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface FooRepository extends JpaRepository<Foo, Long> {
}
and
import javax.persistence.Entity;
#Entity
public class Foo {
}
I am just trying to get a Jpa repo autowired into a test, and I can't. Clearly I'm misunderstanding some small nuance of how Spring Boot works. But even after going through some tutorials, I cannot figure out what I'm missing. Could anyone help me with this?
When you use the annotation #DataJpaTest , it means that you are trying to test only the repository layer. The annotation is used to test JPA repositories and is used in combination with #RunWith(SpringRunner.class) to enable populating the application context. The #DataJpaTest annotation disables full auto-configuration and applies only configuration relevant to JPA tests.So as #fap siggested use it like :
#RunWith(SpringRunner.class)
#DataJpaTest
public class FooRepositoryTest {
#Autowired
private FooRepository fooRepo;
#Test
public void notNull(){
assertNotNull(fooRepo);
}
}
When you use the annotation #RunWith(SpringRunner.class) the SpringRunner provides support for loading a Spring ApplicationContext and having beans #Autowired into your test instance.
You're missing the #RunWith(SpringRunner.class) annotation that tells JUnit to actually start a Spring application for the test.
Your test class should look like
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertNotNull;
#RunWith(SpringRunner.class)
#DataJpaTest
public class FooRepositoryTest {
#Autowired
private FooRepository fooRepo;
#Test
public void notNull(){
assertNotNull(fooRepo);
}
}
The JUnit version used in the question is still JUnit 4.
Spring Boot 2.2.0 switches to JUnit5.
With JUnit5 you'll have to use #ExtendWith(SpringExtension.class) instead of #RunWith(SpringRunner.class). Since #JpaTest is already annotated with #ExtendsWith you don't have to actually include it though, see https://stackoverflow.com/a/65359510/4266296.
I have a new springboot application I am attempting to get started.
The error I receive is
org.springframework.context.ApplicationContextException: Unable to start reactive web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ReactiveWebApplicationContext due to missing ReactiveWebServerFactory bean.
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.onRefresh(ReactiveWebServerApplicationContext.java:76) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
src/main/java/bubbleshadow/RootController.java
package bubbleshadow;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
#RestController
public class RootController {
public RootController() {
}
#GetMapping("/")
public Mono<HttpStatus> returnOk() {
return Mono.just(HttpStatus.OK);
}
}
src/test/java/test/bubbleshadow/RootControllerTest.java
package test.bubbleshadow;
import bubbleshadow.RootController;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
// import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes=RootController.class, webEnvironment = WebEnvironment.RANDOM_PORT)
#AutoConfigureWebTestClient
public class RootControllerTest {
#Autowired
WebTestClient webTestClient;
#Test
public void baseRouteShouldReturnStatusOK() {
webTestClient.head().uri("/").exchange().expectStatus().isOk();
}
}
Your configuration is not sufficient for reactive tests.
The reactive WebTestClient as well as ReactiveWebApplicationContext need reactive server in the application context. Add annotation #EnableAutoConfiguration to your RootControllerTest and let Spring's do it for you.
The autoconfiguration searches your class path and after find reactive classes and reactive context then create ReactiveWebServerFactory bean.
I assume you are using maven to get your dependencies.
I solved the problem by using:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
Instead of:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
For me, the error was being caused by a missing #SpringBootApplication annotation on the Spring class containing the main() method entry point which actually starts the Boot application. Using the following resolved the error:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Likely a corrupt download. Try removing ~/.m2/repository.
You actually just need to change webEnvironment = WebEnvironment.RANDOM_PORT to webEnvironment = WebEnvironment.MOCK in your #SpringBootTest annotation.
#vdou's answer helped me to resolve my issue.
In addition to adding #EnableAutoConfiguration, I also had to manually add the spring application type:
spring:
main:
web-application-type: reactive
There is obviously something in my dependencies that is causing Spring not to be able to discover the type.
I hope this helps somebody...
If you are using Kotlin, check if in your Application class that contains the main method, doesnt have this:
runApplication<Application>{
webApplicationType = WebApplicationType.REACTIVE
}
Then change the "REACTIVE" to "SERVELET", will work like a charm.
If None of the above solutions work, try adding
#ContextConfiguration(loader = AnnotationConfigContextLoader.class)
It may help you
import org.springframework.test.context.support.AnnotationConfigContextLoader;
Yet another reason this can occur is if you're importing in a configuration class for your test that is not marked with #TestConfiguration annotation
I am trying to run my first test with junit on a Spring Web Flow Project from within Eclipse and also from the console with mvn test and but give me the same error.
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [WEB-INF/spring/root-config.xml]; nested exception is java.io.FileNotFoundException: class path resource [WEB-INF/spring/root-config.xml] cannot be opened because it does not exist
I checked and I do have this file in the location so I dont know why Eclipse and Maven is not finding it. Can someone please help me out... below is my test classs
package org.uftwf.memberinquiry.text;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.uftwf.memberinquiry.model.MemberInquiryInformation;
import org.uftwf.memberinquiry.model.MemberRequest;
import org.uftwf.memberinquiry.service.MemberInquiryService;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:/WEB-INF/spring/root-config.xml")
public class TestApp {
#Autowired
private MemberInquiryService service;
#Test
public void testgetMemeberRequestInformation() {
MemberRequest inMemberRequest = new MemberRequest();
MemberInquiryInformation testInfo = service.getMemeberRequestInformation(inMemberRequest);
inMemberRequest.setRequestor("cpilling04#aol.com.dev");
Assert.assertEquals(testInfo.getFirst_Name(), "Christine");
Assert.assertEquals(testInfo.getLast_Name(), "Pillings");
}
}
#ContextConfiguration(locations = {classpath:spring/root-config.xml})
or create
TestApp-context.xml
I updated to the up to date spring-test and junit and now everything is find
#ContextConfiguration(locations = "classpath:WEB-INF/spring/root-config.xml")
When you start the path by /, it is understood, as an absolute path.