Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions checkstyle-suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
on JMockIt Expectations blocks and similar. See https://github.com/checkstyle/checkstyle/issues/3739 -->
<suppress checks="Indentation" files="src[/\\]test[/\\]java"/>
<suppress checks="Regexp" files="DSpaceHttpClientFactory\.java"/>
<suppress checks="Regexp" files="OpenAIRERestConnectorTest\.java"/>
Copy link
Copy Markdown

@vidiecan vidiecan Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? but still approve

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test mocks DSpaceHttpClientFactory itself — to do that, it needs to create an HTTP client independently via HttpClientBuilder.create() and inject it into the mock. Using the factory to create the client that the same factory is supposed to return would defeat the purpose of the mock. The checkstyle rule banning HttpClientBuilder.create() is valid for production code, but this test case is a legitimate exception.

</suppressions>
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,11 @@ public InputStream get(String file, String accessToken) {
break;
}

// do not close this httpClient
result = getResponse.getEntity().getContent();
// the client will be closed, we need to copy the response stream to a new one that we can return
try (InputStream is = getResponse.getEntity().getContent()) {
byte[] bytes = is.readAllBytes();
result = new java.io.ByteArrayInputStream(bytes);
}
}
} catch (MalformedURLException e1) {
getGotError(e1, url + '/' + file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,19 @@ public int getNumberOfResults(String query) {
String encodedQuery = encodeValue(query);

Response projectResponse = connector.searchProjectByKeywords(0, 0, encodedQuery);
return Integer.parseInt(projectResponse.getHeader().getTotal());
if (projectResponse == null || projectResponse.getHeader() == null) {
return 0;
}
String total = projectResponse.getHeader().getTotal();
if (StringUtils.isBlank(total)) {
return 0;
}
try {
return Integer.parseInt(total);
} catch (NumberFormatException e) {
log.error("Failed to parse search result count from OpenAIRE: {}", e.getMessage());
return 0;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.external;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import eu.openaire.jaxb.model.Response;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.dspace.app.client.DSpaceHttpClientFactory;
import org.junit.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;


public class OpenAIRERestConnectorTest {

@Test
public void searchProjectByKeywords() {
try (InputStream is = this.getClass().getResourceAsStream("openaire-projects.xml");
MockWebServer mockServer = new MockWebServer()) {
String projects = new String(is.readAllBytes(), StandardCharsets.UTF_8)
.replaceAll("( mushroom)", "( DEADBEEF)");
mockServer.enqueue(new MockResponse().setResponseCode(200).setBody(projects));

// setup mocks so we don't have to set whole DSpace kernel etc.
// still, the idea is to test how the get method behaves
CloseableHttpClient httpClient = spy(HttpClientBuilder.create().build());
doReturn(httpClient.execute(new HttpGet(mockServer.url("").toString())))
.when(httpClient).execute(Mockito.any());

DSpaceHttpClientFactory mock = Mockito.mock(DSpaceHttpClientFactory.class);
when(mock.build()).thenReturn(httpClient);

try (MockedStatic<DSpaceHttpClientFactory> mockedFactory =
Mockito.mockStatic(DSpaceHttpClientFactory.class)) {
mockedFactory.when(DSpaceHttpClientFactory::getInstance).thenReturn(mock);
OpenAIRERestConnector connector = new OpenAIRERestConnector(mockServer.url("").toString());
Response response = connector.searchProjectByKeywords(0, 10, "keyword");
// Basically check it doesn't throw UnmarshallerException and that we are getting our mocked response
assertTrue("Expected the query to contain the replaced keyword",
response.getHeader().getQuery().contains("DEADBEEF"));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.util.List;
import java.util.Optional;

import eu.openaire.jaxb.model.Response;
import org.dspace.AbstractDSpaceTest;
import org.dspace.external.OpenAIRERestConnector;
import org.dspace.external.factory.ExternalServiceFactory;
import org.dspace.external.model.ExternalDataObject;
import org.dspace.external.provider.ExternalDataProvider;
Expand Down Expand Up @@ -102,4 +104,21 @@ public void testGetDataObjectWInvalidId() {

assertTrue("openAIREFunding.getExternalDataObject.notExists:WRONGID", result.isEmpty());
}

@Test
public void testGetNumberOfResultsWhenResponseIsNull() {
// Create a mock connector that returns null
OpenAIREFundingDataProvider provider = new OpenAIREFundingDataProvider();
provider.setSourceIdentifier("test");
provider.setConnector(new OpenAIRERestConnector("test") {
@Override
public Response searchProjectByKeywords(int page, int size, String... keywords) {
return null;
}
});

// Should return 0 when response is null, not throw NullPointerException
int result = provider.getNumberOfResults("test");
assertEquals("Should return 0 when response is null", 0, result);
}
}
Loading