forked from IQSS/dataverse
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api-test): add JUnit5 extension for RandomUser IQSS#8251
Many API tests require the use of a random user, which is no SuT (subject under test). To gather such a user and ensure its deletion from a target Dataverse instance after a test, this extension provides a convenient way. Simple use ExtendWith and provide a RandomUser parameter, you're done.
- Loading branch information
1 parent
e34d71e
commit 4b3a941
Showing
2 changed files
with
172 additions
and
0 deletions.
There are no files selected for viewing
55 changes: 55 additions & 0 deletions
55
src/test/java/edu/harvard/iq/dataverse/api/helpers/RandomUser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package edu.harvard.iq.dataverse.api.helpers; | ||
|
||
import com.jayway.restassured.path.json.JsonPath; | ||
import com.jayway.restassured.response.Response; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* A class to represent a random user, retrieved from a Dataverse instance via its API | ||
* | ||
* There are some often used detail fields accessible via methods added for convenience. | ||
* All fields from the JSON response may be accessed, too. | ||
*/ | ||
public class RandomUser { | ||
|
||
private static final String statusPath = "status"; | ||
private static final String dataPath = "data"; | ||
private static final String apiTokenPath = dataPath+".apiToken"; | ||
private static final String usernamePath = dataPath+".user.userName"; | ||
private static final String authUserPath = dataPath+".authenticatedUser"; | ||
private static final String persistentUserIdPath = authUserPath+".persistentUserId"; | ||
|
||
private final JsonPath json; | ||
|
||
/** | ||
* Package-private on intention - should only be created by {@link RandomUserExtension} | ||
*/ | ||
RandomUser(Response response) { | ||
this.json = response.jsonPath(); | ||
} | ||
|
||
public String getStatus() { | ||
return json.get(statusPath); | ||
} | ||
|
||
public String getApiToken() { | ||
return json.get(apiTokenPath); | ||
} | ||
|
||
public String getUsername() { | ||
return json.get(usernamePath); | ||
} | ||
|
||
public Map<String, String> getAuthenticatedUser() { | ||
return json.get(authUserPath); | ||
} | ||
|
||
public String getPersistentUserId() { | ||
return json.get(persistentUserIdPath); | ||
} | ||
|
||
public String toString() { | ||
return "RandomUser["+json.getJsonObject("").toString()+"]"; | ||
} | ||
} |
117 changes: 117 additions & 0 deletions
117
src/test/java/edu/harvard/iq/dataverse/api/helpers/RandomUserExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package edu.harvard.iq.dataverse.api.helpers; | ||
|
||
import com.jayway.restassured.http.ContentType; | ||
import com.jayway.restassured.response.Response; | ||
import edu.harvard.iq.dataverse.api.UtilIT; | ||
import org.junit.jupiter.api.extension.AfterTestExecutionCallback; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.junit.jupiter.api.extension.ExtensionContext; | ||
import org.junit.jupiter.api.extension.ExtensionContext.Store; | ||
import org.junit.jupiter.api.extension.ExtensionContext.Namespace; | ||
import org.junit.jupiter.api.extension.ParameterContext; | ||
import org.junit.jupiter.api.extension.ParameterResolutionException; | ||
import org.junit.jupiter.api.extension.ParameterResolver; | ||
|
||
import javax.servlet.http.HttpServletResponse; | ||
import java.lang.reflect.Parameter; | ||
import java.util.Arrays; | ||
import java.util.logging.Logger; | ||
|
||
import static org.junit.jupiter.api.Assumptions.assumeFalse; | ||
import static org.junit.jupiter.api.Assumptions.assumeTrue; | ||
|
||
/** | ||
* A JUnit5 extension to resolve a parameter of a test method and inject a {@link RandomUser} into it. | ||
* This user may be used to create/use other resources and subjects under test. | ||
*/ | ||
public class RandomUserExtension implements ParameterResolver, AfterTestExecutionCallback { | ||
|
||
private static final Logger logger = Logger.getLogger(RandomUserExtension.class.getCanonicalName()); | ||
|
||
private Store getStore(ExtensionContext context) { | ||
return context.getStore(Namespace.create(getClass(), context.getRequiredTestClass(), context.getRequiredTestMethod())); | ||
} | ||
|
||
@Override | ||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { | ||
return parameterContext.getParameter().getType().equals(RandomUser.class); | ||
} | ||
|
||
@Override | ||
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { | ||
Store store = getStore(extensionContext); | ||
String parameterName = parameterContext.getParameter().getName(); | ||
|
||
RandomUser user = getNewRandomUser(); | ||
store.put(parameterName, user); | ||
return user; | ||
} | ||
|
||
/** | ||
* Create a new RandomUser via Dataverse API | ||
* Hint: package-private on purpose to allow reuse within other of our extensions | ||
* | ||
* @return a new random user (or nothing, when assumptions aren't met) | ||
*/ | ||
static RandomUser getNewRandomUser() { | ||
// request user via API | ||
Response createUser = UtilIT.createRandomUser(); | ||
|
||
// assume created or abort | ||
assumeTrue(ContentType.fromContentType(createUser.contentType()) == ContentType.JSON, | ||
() -> "Return data for was no JSON: "+createUser.print()); | ||
assumeTrue(createUser.getStatusCode() == HttpServletResponse.SC_OK, | ||
() -> "User creation failed with status "+createUser.getStatusCode()+": "+createUser.print()); | ||
|
||
// store response as user | ||
RandomUser user = new RandomUser(createUser); | ||
|
||
// verify user | ||
assumeTrue(user.getUsername() != null, () -> "Could not find a username for successfully created user."); | ||
assumeFalse(user.getUsername().isEmpty(), () -> "Could not find a non-empty username for successfully created user."); | ||
assumeFalse(user.getUsername().isBlank(), () -> "Could not find a non-blank username for successfully created user."); | ||
assumeTrue(user.getApiToken() != null, () -> "Could not find an api token for successfully created user."); | ||
assumeFalse(user.getApiToken().isEmpty(), () -> "Could not find a non-empty api token for successfully created user."); | ||
assumeFalse(user.getApiToken().isBlank(), () -> "Could not find a non-blank api token for successfully created user."); | ||
|
||
return user; | ||
} | ||
|
||
@Override | ||
public void afterTestExecution(ExtensionContext extensionContext) throws Exception { | ||
Store store = getStore(extensionContext); | ||
|
||
// iterate all parameters | ||
for (Parameter p : extensionContext.getRequiredTestMethod().getParameters()) { | ||
// if type matches ... | ||
if (p.getType() == RandomUser.class) { | ||
// ... retrieve user from store | ||
RandomUser user = store.get(p.getName(), RandomUser.class); | ||
// and delete if present | ||
if (user != null) { | ||
deleteRandomUser(user); | ||
} else { | ||
// if not present, log an info, as this seems not right (but might have happened when creation failed) | ||
logger.info("Could not find a previously stored RandomUser for parameter "+p.getName()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Delete a RandomUser via Dataverse API | ||
* Hint: package-private on purpose to allow reuse within other of our extensions | ||
* | ||
* @param user A random user created via the Dataverse API before | ||
*/ | ||
static void deleteRandomUser(RandomUser user) { | ||
// delete via API | ||
logger.info("Deleting user "+user.getUsername()); | ||
Response deleteUser = UtilIT.deleteUser(user.getUsername()); | ||
|
||
// if this does not work, log a warning, but continue (try to delete the others) | ||
if (deleteUser.getStatusCode() != HttpServletResponse.SC_OK) { | ||
logger.warning("Could not delete user "+user.getUsername()+": "+deleteUser.print()); | ||
} | ||
} | ||
} |