ClassNotFoundException: org.junit.Assert exception when using MockRestServiceServer - spring-boot

I'm trying to run the following test
import org.springframework.test.web.client.MockRestServiceServer;
....
#Test
void successPost () {
MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build();
server.expect(once(), requestTo("http://localhost:8080/test"))
.andExpect(header("X-AUTH", "myToken"))
.andRespond(withSuccess("{ \"msg\":\"hi\"}", MediaType.APPLICATION_JSON));
WebClient<String, DummyResponse> client = new WebClient<>(restTemplate, retryTemplate, DummyResponse.class);
DummyResponse result = client.post("http://localhost:8080","/test", "myRequest", "myToken");
// Verify all expectations met
server.verify();
assertThat(result.getMsg(), is("hi"));
}
and it fails with when I have .andExpect(header("X-AUTH", "myToken"))
ClassNotFoundException: org.junit.Assert
Project contains only JUnit 5 dependencies and
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.0.RELEASE</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>

Related

Spring Security context is always null in Spring Boot Cucumber Test

I have created a service with Spring Boot and Reactor. I try to test with Cucumber.
POM file (extract):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console</artifactId>
<scope>test</scope>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-bom</artifactId>
<version>7.10.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
My cucumber configuration looks like this:
#Suite
class CucumberTestRunner
#CucumberContextConfiguration
#ContextConfiguration(classes = [CucumberBootstrap::class])
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = [MyApplication::class])
class CucumberSpringContextConfig
#ComponentScan("com.mypackage")
#Configuration
class CucumberBootstrap
The step definition I'm working on is like this:
#ScenarioScope
class MyTestStepDefs(
private val service: MyService
) {
#Given("User is authenticated")
fun userIsAuthenticated() {
val auth = UsernamePasswordAuthenticationToken(
User("username", "password", emptyList()),
"credentials",
emptyList<GrantedAuthority>()
)
val context = ReactiveSecurityContextHolder.getContext().block()
//ReactiveSecurityContextHolder.getContext()
// .doOnNext { it.authentication = auth }
// .block()
}
...
}
I would like to set the authenticated user into the security context. But unfortunately, the security context is always null.
I have also regular Springt Boot Tests running, where the security context is correctly returned. Here is an extract:
#SpringBootTest(webEnvironment = RANDOM_PORT)
#Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyControllerTests #Autowired constructor(
private val client: WebTestClient
) {
#Test
#WithMockUser
fun `post instruction set`() {
val context = ReactiveSecurityContextHolder.getContext().block()
...
}
...
}
The service class is injected correctly into the step definitions class.
Does anyone have a hint what's missing in the configuration?
Thanks in advance for your help!
The tests that work use the #WithMockUser annotation which work (as described here) because this enables the WithSecurityContextTestExecutionListener.
Unfortunately you can't use this with Cucumber, Cucumber doesn't have a single test method. But ultimately this listener sets the context using:
this.securityContextHolderStrategyConverter.convert(testContext).setContext(supplier.get())
This then invokes (via some indirection):
TestSecurityContextHolder.setContext(context)
Which you could do inside Cucumber too. Though you may want to review the implementation of the WithSecurityContextTestExecutionListener for what exactly you're trying to reproduce.
Alternatively you can do your test end-to-end including the authentication.
Based on M.P. Korstanje's description, I implemented the step as follows:
#Given("User is authenticated")
fun userIsAuthenticated() {
val auth = UsernamePasswordAuthenticationToken(
User("username", "password", emptyList()),
"credentials",
emptyList<GrantedAuthority>()
)
val context = TestSecurityContextHolder.getContext()
context.authentication = auth
val newContext = ReactiveSecurityContextHolder.getContext().block()
assertEquals(auth, newContext?.authentication, "Wrong authentication stored in security context")
}

Problem inserting entities in database with #BeforeAll

i'm trying to insert some entities in my H2 database to run some unit tests, for this im using a setup method decorated with the #BeforeAll annotation like so :
#RunWith(SpringRunner.class)
#DataJpaTest
public class ItemRepositoryTest {
#Autowired
private ItemRepository itemRepo;
#Autowired
private CategoryRepository catRepo;
#BeforeAll
public static void setup(#Autowired ItemRepository itemRepo) {
Category cat_0 = new Category(0L, "category_0");
Category cat_1 = new Category(1L, "category_1");
Category cat_2 = new Category(2L, "category_2");
Item item_0 = new Item(0L, "item_0", "...", 7.99, "0000000000000", "imgUrl", Set.of(cat_0, cat_1));
Item item_1 = new Item(1L, "item_1", "...", 8.99, "1111111111111", "imgUrl", Set.of(cat_2));
Item item_2 = new Item(2L, "item_2", "...", 9.99, "2222222222222", "imgUrl", Set.of(cat_0, cat_1, cat_2));
itemRepo.saveAll(List.of(item_0, item_1, item_2));
}
#AfterAll
public static void clean(#Autowired ItemRepository itemRepo, #Autowired CategoryRepository catRepo) {
itemRepo.deleteAll();
catRepo.deleteAll();
}
#Test
public void items_should_have_been_saved() {
List<Item> items = itemRepo.findAll();
assertThat(items).hasSize(3);
}
}
The 'items_should_have_been_saved' Test fails (Expected size: 3 but was: 0), it seems my 'setup' method does not work, can anybody tell me what im doing wrong ? (I'm using SpringBoot 2.5.0)
src/test/resources/aplication.properties:
#----------------------------------------------------------------------------------
# CONFIG H2
#----------------------------------------------------------------------------------
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;IGNORECASE=TRUE;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.defer-datasource-initialization=true
#----------------------------------------------------------------------------------
server.error.include-message=always
spring.sql.init.platform=h2
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>net.kaczmarzyk</groupId>
<artifactId>specification-arg-resolver</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

Spring Boot REST endpoints not working , if add own dependencies in maven file

I developed spring boot application (name as App1) with that app i'm connecting to the MQs( messaging queues ex: IBM MQ), App1 maven dependencies i'm added to the App2 and calling the App1 methods for connecting to the MQ's, but here i'm facing problem whenever add App1 dependencies into App2 then App2 REST endpoints are not working(giving 404 response), could you please help me what might be the problem
Note: if i remove the App1 dependencies in App2 then ,here REST controllers are working
App2 REST Controller Code:
#RestController
#RequestMapping("/accept")
public class RequestController {
#Autowired
private Connector connector;
#PostMapping
public ResponseEntity<String> sendRequestTransactionEvent(#RequestBody TEvent tEvent) {
//System.out.println("Received tEvent) request: " + tEvent)
System.out.println("rquest came to the controller");
connector.sendRequestTransactionEvent(tEvent);
return new ResponseEntity<String>("message successfully sent ", HttpStatus.OK);
}
}
App1 pom.xml file:
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel-version}</version>
</dependency>
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>mq-jms-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>${camel-version}</version>
</dependency>
</dependencies>
App2 pom.xml file
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.app1</groupId>
<artifactId>Env4x1-Mqjms</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

Spring boot unit test are not running

I have tried many solution to fix this problem. But no luck My test cases are not running.
When i did the mvn clean package, it is running single test case.
Service layer test
#SpringBootTest
#RunWith(SpringRunner.class)
public class OrderStatusServiceTests {
#Autowired
private OrderStatusServiceImpl orderStatusService;
#MockBean
private OrderStatusRepository orderStatusRepository;
#Before
public void initialize(){
orderStatusService = new OrderStatusServiceImpl(orderStatusRepository);
}
#Test
public void saveOrderDetail(){
OrderDetail orderDetail = getOrderInformation();
Mockito.when(orderStatusRepository.save(orderDetail)).thenReturn(orderDetail);
Assert.assertEquals(orderStatusService.addOrderDetail(orderDetail), orderDetail);
}
#Test
public void getOrderDetail(){
OrderDetail orderDetail = getOrderInformation();
Mockito.when(orderStatusRepository.findByUserId("abc123")).thenReturn(java.util.Optional.of(orderDetail));
Assert.assertEquals(orderStatusService.getOrderDetail("abc123"), java.util.Optional.of(orderDetail));
}
}
Actually, the problem was with pom file.
Maven file while getting the error.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
What i did is removed the exclusion and Junit additional dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

Spring reactive boot app (2.0.0.RC1) as servlet in WebLogic 12c starts but NPE thrown on access

Running Spring boot reactive application based off of 2.0.0.RC1. It works by itself with a netty embedded container just fine.
Switching it to a servlet, sorting out the dependencies - exclusions, provisions, weblogic.xml instructions etc, then deploying to WebLogic 12c (12.1.3) container will start the application successfully. However when trying to access the rest url, handled by a single controller, WebLogic throws NPE. It never reaches Spring controller.
Error 500--Internal Server Error
java.lang.NullPointerException
at weblogic.servlet.internal.ServletResponseImpl.sendContentError(ServletResponseImpl.java:713)
at weblogic.servlet.internal.ServletResponseImpl.sendError(ServletResponseImpl.java:761)
at weblogic.servlet.internal.ServletResponseImpl.sendError(ServletResponseImpl.java:693)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.handleErrorStatus(ErrorPageFilter.java:144)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:117)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.access$000(ErrorPageFilter.java:59)
at org.springframework.boot.web.servlet.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:90)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:108)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3451)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.__run(WebAppServletContext.java:3417)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2280)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2196)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2174)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1632)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:256)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
I will paste the excerpts of all relevant sources below. First boot app:
#SpringBootApplication
#Configuration
//#EnableAutoConfiguration
//#ComponentScan(basePackages = {"ca.corp.uservice", "ca.corp.uservice.filecache"})
//#ImportResource({"/WEB-INF/ws-dispatcher-servlet.xml"})
//#EnableWebSecurity
public class FileCacheBootApp extends SpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) {
SpringApplication.run(FileCacheBootApp.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(FileCacheBootApp.class);
}
...
}
Next the controller:
#RestController
#RequestMapping("/filecache")
public class FileCacheController implements FileCacheApi {
#Autowired
private FileCacheRepository repo;
// -------------- GET ---------------
#GetMapping(value = "{token}")
#Override public Mono<FileCacheable> get(#PathVariable("token") String token) {
return repo.findByToken(token).map(f -> load(f));
}
#GetMapping(value = "app")
#Override public Mono<FileCacheable> get(#RequestParam Long appid, #RequestParam String type, #RequestParam Integer langcode) {
return repo.findByUnique(appid, type, langcode).map(f -> load(f));
}
#GetMapping(value = "zip")
#Override public Mono<FileCacheable> get(#RequestParam String name, #RequestParam Integer langcode) {
return repo.findByNameAndLang(name, langcode);
}
...
}
And finally pom, spring fmw and servlet. Needed to do some jumps here to get it to run w/o conflicts in WebLogic container.
<!-- SPRING FRAMEWORK -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot-version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
<version>${spring-boot-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>${spring-boot-version}</version>
<exclusions>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- SERVLET, VALIDATION and EL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.1-b04</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b09</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.1.Final</version>
</dependency>
Weblogic.xml
<weblogic-version>12.1.3</weblogic-version>
<context-root>file-cache-uservice</context-root>
<container-descriptor>
<prefer-application-packages>
<package-name>org.springframework.*</package-name>
<package-name>org.hibernate.*</package-name>
<package-name>javax.validation.*</package-name>
<package-name>javax.validation.spi.*</package-name>
<package-name>org.apache.logging.log4j.*</package-name>
<package-name>org.slf4j.*</package-name>
</prefer-application-packages>
</container-descriptor>
I am trying to be as specific as possible w/o being an info overkill. If you'd like to know more details though... be glad to provide.
Any info or a pointer on the source of the NPE is appreciated.
Solved it. This bit was confusing... I added a dependency for the boot-web back in:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot-version}</version>
<exclusions>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
and then everything started responding. Which kind of makes sense except for the fact that you can't have that dependency if you run WebFlux boot stand alone.
It's a bit unclear as to why standalone (embedded container) cannot have web dependency, and external container must have it. But it works now.

Resources