NoSuchMethodError with spring-webmvc upgrade - java

We upgraded to spring-webmvc 5.2.3.RELEASE.
This is causing a JUnit to fail.
I think the issue is with the .build() method - it can't be found.
The code:
#RunWith(MockitoJUnitRunner.class)
public class CommunicationDeliveryControllerTest {
#InjectMocks
CommunicationDeliveryController controller = new CommunicationDeliveryController();
#Mock
private RequestHandler requestHandler;
#Mock
private HttpServletRequest httpServletRequest;
private MockMvc mockMvc;
private Gson gson = new Gson();
private CommunicationDeliveryController spiedController;
#Before
public void setup() {
spiedController = spy(controller);
mockMvc = standaloneSetup(spiedController).build();
}
#Test
public void initiateBatchRunTest() throws Exception{
MvcResult result = mockMvc.perform(post("/api/BatchRun").contentType(MediaType.APPLICATION_JSON_VALUE).content(gson.toJson(BulkCommunicationRequestData.getBulkEmailRequestForPositive()))).andReturn();
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
}
#Test
public void deliverCommunicationTest() throws Exception{
MvcResult result = mockMvc.perform(post("/api/deliverCommunication").contentType(MediaType.APPLICATION_JSON_VALUE).content(gson.toJson(BulkCommunicationRequestData.populateAllEmailDetail()))).andReturn();
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
}
}
The error:
java.lang.NoSuchMethodError: org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder$StandaloneConfiguration.getInterceptors()[Ljava/lang/Object;
at company.custcomm.service.communicationdelivery.controllers.CommunicationDeliveryControllerTest.setup(CommunicationDeliveryControllerTest.java:45)
Are there compatibility issues between our versions of spring-webmvc, mockito, and JUnit?
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>

I upgrade all spring dependencies to 4.3.18-RELEASE, then there is no error any more.

Is there a specific version of spring-test in your dependencies?
I ran into a similar problem a while ago - turned out that there was a strict version limit for spring-test, and upgrading it to 5.2.3-RELEASE resolved the issue.

If you do not want to change the version of your Junit and spring-webmvc then you can specify spring-test version explicitly in your pom.xml. This works for me.
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.0.RELEASE</version>
<scope>test</scope>
</dependency>

Related

JAVA.NET.HTTP.HTTPClient returns InaccessibleObjectException Error Using Junit5+Mockito

I am running into the following exception while trying to test my Java application with Junit5 and Mockito.Given below are the exception, code snippet and the dependencies used. Any insight would be highly appreciated.
java.lang.reflect.InaccessibleObjectException: Unable to make protected java.net.http.HttpClient() accessible: module java.net.http does not "opens java.net.http" to unnamed module #131ef10
#RunWith(MockitoJUnitRunner.class)
public class StudentRegisterServiceTest {
#Mock
HttpClient client;
#Mock
HttpRequest request;
#Mock
HttpResponse<String> response;
#Test
public void testPopulateStudentDetails() throws IOException, InterruptedException{
Properties configFile = mock(Properties.class);
StudentRegisterService studentService = new StudentRegisterService();
when(configFile.getProperty(anyString())).thenReturn("");
when(configFile.getProperty(anyString()))
.thenReturn("https://example.com");
when(client.send(any(HttpRequest.class), eq(HttpResponse.BodyHandlers.ofString()))).thenReturn(response);
studentService.populateStudentDetails(studentID, configFile);
}
}
------------
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.1.1</version>
<scope>test</scope>
</dependency>

InvalidTestClassError: Invalid test class. How to test spring boot with maven and #BeforeAll/Class initializator

I have the gradle project where I successfully use tests and try to implement the same solution with maven, but I totally can't execute tests there.
Main problem in that I need to use #BeforeAll/Class annotation and init NOT static method.
In the Gradle this works so:
build.gradle
dependencies {
testImplementation "org.springframework.boot:spring-boot-starter-test:${spring_boot_version}"
implementation 'junit:junit:4.13.1'
....
}
tasks.named('test') {
useJUnitPlatform()
}
test classes:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = {DeardiaryApplication.class})
#WebAppConfiguration
public abstract class AbstractTest {
protected MockMvc mvc;
private ObjectMapper objectMapper = new ObjectMapper();
#Autowired
WebApplicationContext webApplicationContext;
protected void setUp() {
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
...
}
import org.junit.jupiter.api.*;
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class DatabaseTest extends AbstractTest {
#Autowired
private ExerciseInterface exerciseService;
#BeforeAll
public void init() {
setUp();
exerciseDto = exerciseService.getByExerciseType(ExerciseTypeEnum.SNATCH).get(0);
}
#Test
....
But in the maven project I received InvalidTestClassError: Invalid test class.
When I use junit.Test instead junit.jupiter.api.Test, the #BeforeAll/Class method nod called, or I received error BeforeAll must be static, etc...
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M8</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
This is all difference - classes implemented in the same way
If you don't want to use the static method for BeforeAll, you need to use the annotation TestInstance(Lifecycle.PER_CLASS)
By default the Junit uses PER_METHOD lifecycle, thus the BeforeAll requires it to be static to ensure it is not instantiated with every method.
The TestInstance(Lifecycle.PER_CLASS) annotation ensures that the lifecycle of the test is per class thus removing the requirement of static BeforeAll.

Cannot persist via Hibernate ORM with Panache using rubenlagus/TelegramBots

I'm using Quarkus 2.15.1 and rubenlagus/TelegramBots 6.3.0
My pom.xml dependencies are:
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
<version>6.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
I've configured jdbc URL, username & password as well.
The problem is when I'm trying to persist an object (via Active Record or Repository pattern) there is an exception.
The code snippet is:
#ApplicationScoped
public class VoteBot extends TelegramLongPollingBot {
#Override
public void onUpdateReceived(Update update) {
if (update.hasMessage() && update.getMessage().hasText()) {
long chatId = update.getMessage().getChatId();
String messageText = update.getMessage().getText();
if (messageText.matches("^[A-Za-z\\s]+$")) {
Participant participant = new Participant();
participant.setChatId(chatId);
participant.setName(messageText);
// Some code
Participant.persist(participant); // Here is the exceptional line goes
// Some code
}
}
Startup class looks like:
#ApplicationScoped
public class Application {
void onStart(#Observes StartupEvent ev) {
try {
TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class);
telegramBotsApi.registerBot(new VoteBot());
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
}
The exception message is:
2022-12-25 02:22:19,727 ERROR [org.tel.tel.upd.DefaultBotSession] (ckorovoda_vote_bot Telegram Executor) Cannot use the EntityManager/Session because neither a transaction nor a CDI request context is active. Consider adding #Transactional to your method to automatically activate a transaction, or #ActivateRequestContext if you have valid reasons not to use transactions.: javax.enterprise.context.ContextNotActiveException: Cannot use the EntityManager/Session because neither a transaction nor a CDI request context is active. Consider adding #Transactional to your method to automatically activate a transaction, or #ActivateRequestContext if you have valid reasons not to use transactions.
at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.acquireSession(TransactionScopedSession.java:106)
at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.contains(TransactionScopedSession.java:325)
at org.hibernate.engine.spi.SessionLazyDelegator.contains(SessionLazyDelegator.java:710)
at org.hibernate.Session_5b93bee577ae2f8d76647de04cfab36afbf52958_Synthetic_ClientProxy.contains(Unknown Source)
at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.persist(AbstractJpaOperations.java:100)
at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.persist(AbstractJpaOperations.java:96)
at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.persist(AbstractJpaOperations.java:112)
at io.quarkus.hibernate.orm.panache.PanacheEntityBase.persist(PanacheEntityBase.java:756)
at store.ckorovoda.Participant.persist(Participant.java)
at store.ckorovoda.VoteBot.onUpdateReceived(VoteBot.java:74)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.telegram.telegrambots.meta.generics.LongPollingBot.onUpdatesReceived(LongPollingBot.java:27)
at org.telegram.telegrambots.updatesreceivers.DefaultBotSession$HandlerThread.run(DefaultBotSession.java:317)
I've tried adding #Transactional, #ActivateRequestContext and changing bean scopes. I've also tried to use EntityManager and quarkus-narayana-jta. However, I'm pretty sure it's all connected with this 3rd-party lib for Telegram.
I'm stuck with it and will appreciate any recommendation or hints for resolving that stuff.
Thank you!

Upgrading org.testcontainers from 1.10.6 to 1.15.1 - PostgreSQLContainer.start() dissapears

I upgraded my org.testcontainers:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.15.1</version>
<scope>test</scope>
</dependency>
but then I can't use the start() method anymore:
public class ComponentTest {
public static final PostgreSQLContainer<?> postgreDBContainer = new
PostgreSQLContainer<>("postgres:13");
static {
postgreDBContainer.start();
}
}
Is there any solution to that issue?
May be you missed additional dependency?
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.15.1</version>
<scope>test</scope>
</dependency>

How to mock a private method using PowerMock with Mockito and TestNG

I am trying to use powermock to mock a private method, but my PowerMock is not recognized in MockitoBusinessOperation MockitoBusinessOperation = PowerMock.createPartialMock(MockitoBusinessOperation.class, "inTestMethod"); . I used maven and the dependencies for mockito and powermock are defined in my pom file
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-mockito-release-full</artifactId>
<version>1.4.9</version>
<scope>test</scope>
</dependency>
I don't know if the error is related to powermock with TestNG or I am doing some mistake in my code.
#PrepareForTest(MockitoBusinessOperation.class)
#Test(enabled = true)
public void testReCalculatePrepaids() throws Exception {
MockitoBusinessOperation MockitoBusinessOperation = PowerMock.createPartialMock(MockitoBusinessOperation.class, "inTestMethod");
PowerMock.expectPrivate(MockitoBusinessOperation, "inTestMethod", Id).andReturn("working fine");
when(MockitoBusinessService.creditReport(this.Id)).thenReturn(new String("Decline by only Me"));
String report = MockitoBusinessService.creditReport(this.Id);
String mainReport = MockitoBusinessOperation.creditAproved(this.Id);
}
someone has an idea or any clue lead to the solution
According to the documentation your maven file should have the following definitions:
<properties>
<powermock.version>1.5</powermock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-testng</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
please try this way
#Test
public void commandEndHandlerTest() throws Exception
{
Method retryClientDetail_privateMethod =yourclass.class.getDeclaredMethod("Your_function_name",null);
retryClientDetail_privateMethod.setAccessible(true);
retryClientDetail_privateMethod.invoke(yourclass.class, null);
}

Categories