1 year ago
#381726
Laiv
Why my Jenkins JUnit test no longer works?
A bit of context.
I'm developing an extensi贸n for Jenkins, that consists of a new WEB API aimed to provide our ALM tooling with customized endpoints and features. The starting point for me was this guide, which I have reproduced step by step.
After some manual tests of a bare minimum API, I concluded that the extension was ready for further development. However, I wanted to make the test automatic during the build phase, so I implemented a canary test following the previous guide and this other to feed test with @LocalData
.
The firsts times I run the JUnit, everything went as expected. Test passed. I was able to run mvn clean packge
and complete the tests.
Today, I did open the IDE, run the same maven goals to ensure that everything was ok, but all my test failed due to an 404 Not Found
=== Starting test_ping(net.corp.jenkins.plugins.almapirest.AlmApiTest)
0.132 [id=17] INFO o.jvnet.hudson.test.WarExploder#explode: Picking up existing exploded jenkins.war at /home/*****/Desarrollo/workspace-11/jenkins-plugins/imi-alm-jenkinsplugin-almapirest/target/jenkins-for-test
0.493 [id=17] INFO o.jvnet.hudson.test.JenkinsRule#createWebServer: Running on http://localhost:37423/jenkins/
1.011 [id=31] INFO jenkins.InitReactorRunner$1#onAttained: Started initialization
2.381 [id=29] INFO hudson.PluginManager#considerDetachedPlugin: Loading a detached plugin as a dependency: /tmp/jenkins14603157886504547615/plugins/bouncycastle-api.jpi
2.488 [id=29] INFO hudson.PluginManager#considerDetachedPlugin: Loading a detached plugin as a dependency: /tmp/jenkins14603157886504547615/plugins/command-launcher.jpi
2.501 [id=29] INFO hudson.PluginManager#considerDetachedPlugin: Loading a detached plugin as a dependency: /tmp/jenkins14603157886504547615/plugins/jdk-tool.jpi
2.521 [id=29] INFO hudson.PluginManager#considerDetachedPlugin: Loading a detached plugin as a dependency: /tmp/jenkins14603157886504547615/plugins/jaxb.jpi
2.774 [id=33] INFO jenkins.InitReactorRunner$1#onAttained: Listed all plugins
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.google.inject.internal.cglib.core.$ReflectUtils$2 (file:/home/*****/.m2/repository/com/google/inject/guice/4.0/guice-4.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of com.google.inject.internal.cglib.core.$ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
6.059 [id=35] INFO jenkins.InitReactorRunner$1#onAttained: Prepared all plugins
6.086 [id=29] INFO jenkins.InitReactorRunner$1#onAttained: Started all plugins
6.096 [id=29] INFO jenkins.InitReactorRunner$1#onAttained: Augmented all extensions
7.084 [id=31] INFO jenkins.InitReactorRunner$1#onAttained: System config loaded
7.085 [id=31] INFO jenkins.InitReactorRunner$1#onAttained: System config adapted
7.085 [id=35] INFO jenkins.InitReactorRunner$1#onAttained: Loaded all jobs
7.087 [id=33] INFO jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated
7.176 [id=35] INFO jenkins.InitReactorRunner$1#onAttained: Completed initialization
9.127 [id=17] INFO n.o.j.p.almapirest.AlmApiTest#logJenkinsWebResponse: <html><body>
**<h1>404 Not Found</h1>**
<p>Stapler processed this HTTP request as follows, but couldn't find the resource to consume the request
<pre>
-> evaluate(<hudson.model.Hudson@15789a13> :hudson.model.Hudson,"/alm-api/ping")
-> evaluate(((StaplerProxy)<hudson.model.Hudson@15789a13>).getTarget(),"/alm-api/ping")
-> evaluate(<hudson.model.Hudson@15789a13>.getDynamic("alm-api",...),"/ping")
hudson.model.Hudson@15789a13.getDynamic("alm-api",...)==null. Back tracking.
-> evaluate(((StaplerFallback)<hudson.model.Hudson@15789a13>).getStaplerFallback(),"/alm-api/ping")
-> evaluate(<hudson.model.AllView@52446fb2[view/all/]> :hudson.model.AllView,"/alm-api/ping")
-> evaluate(<hudson.model.AllView@52446fb2[view/all/]>.getDynamic("alm-api",...),"/ping")
hudson.model.AllView@52446fb2[view/all/].getDynamic("alm-api",...)==null. Back tracking.
<font color=red>-> No matching rule was found on <hudson.model.AllView@52446fb2[view/all/]> for "/alm-api/ping"</font>
</pre>
<p><hudson.model.AllView@52446fb2[view/all/]> has the following URL mappings, in the order of preference:<ol>
<li>
If path ends without '/' insert it
<li>
hudson.model.View.doChildrenContextMenu(...) for url=/childrenContextMenu/...
<li>
hudson.model.AllView.doCreateItem(...) for url=/createItem/...
<li>
hudson.model.View.doConfigSubmit(...) for url=/configSubmit/...
<li>
hudson.model.View.doCheckJobName(...) for url=/checkJobName/...
<li>
hudson.model.View.doItemCategories(...) for url=/itemCategories/...
<li>
hudson.model.View.doConfigDotXml(...) for url=/config.xml/...
<li>
hudson.model.View.doDoDelete(...) for url=/doDelete/...
<li>
hudson.model.View.doSubmitDescription(...) for url=/submitDescription/...
<li>
hudson.model.View.doRssAll(...) for url=/rssAll/...
<li>
hudson.model.View.doRssFailed(...) for url=/rssFailed/...
<li>
hudson.model.View.doRssLatest(...) for url=/rssLatest/...
<li>
VIEW.groovy for url=/VIEW
<li>
VIEW.gsp for url=/VIEW
<li>
VIEW.jelly for url=/VIEW
<li>
index view of org.kohsuke.stapler.jelly.groovy.GroovyFacet@5a1e412f for url=/
<li>
index view of org.kohsuke.stapler.jelly.JellyFacet@5b7c0578 for url=/
<li>
BLOCKED: class java.lang.String hudson.model.AllView.DEFAULT_VIEW_NAME for url=/DEFAULT_VIEW_NAME/...
<li>
BLOCKED: class hudson.util.DescriptorList hudson.model.View.LIST for url=/LIST/...
<li>
BLOCKED: interface java.util.Comparator hudson.model.View.SORTER for url=/SORTER/...
<li>
BLOCKED: class hudson.security.PermissionGroup hudson.model.View.PERMISSIONS for url=/PERMISSIONS/...
<li>
BLOCKED: class hudson.security.Permission hudson.model.View.CREATE for url=/CREATE/...
<li>
BLOCKED: class hudson.security.Permission hudson.model.View.DELETE for url=/DELETE/...
<li>
BLOCKED: class hudson.security.Permission hudson.model.View.CONFIGURE for url=/CONFIGURE/...
<li>
BLOCKED: class hudson.security.Permission hudson.model.View.READ for url=/READ/...
<li>
BLOCKED: class hudson.util.AlternativeUiTextProvider$Message hudson.model.View.NEW_PRONOUN for url=/NEW_PRONOUN/...
<li>
BLOCKED: hudson.security.ACL hudson.model.View.getACL() for url=/aCL/...
<li>
hudson.model.ViewDescriptor hudson.model.View.getDescriptor() for url=/descriptor/...
<li>
BLOCKED: java.lang.String hudson.model.AllView.getDisplayName() for url=/displayName/...
<li>
BLOCKED: hudson.search.SearchIndex hudson.model.AbstractModelObject.getSearchIndex() for url=/searchIndex/...
<li>
BLOCKED: java.lang.String hudson.model.AbstractModelObject.getSearchName() for url=/searchName/...
<li>
BLOCKED: java.lang.String hudson.model.View.getSearchUrl() for url=/searchUrl/...
<li>
hudson.search.Search hudson.model.AbstractModelObject.getSearch() for url=/search/...
<li>
BLOCKED: java.util.Collection hudson.model.AllView.getItems() for url=/items/...
<li>
BLOCKED: hudson.Indenter hudson.model.View.getIndenter() for url=/indenter/...
<li>
hudson.model.Api hudson.model.View.getApi() for url=/api/...
<li>
hudson.model.BuildTimelineWidget hudson.model.View.getTimeline() for url=/timeline/...
<li>
hudson.model.View$AsynchPeople hudson.model.View.getAsynchPeople() for url=/asynchPeople/...
<li>
hudson.model.View$People hudson.model.View.getPeople() for url=/people/...
<li>
hudson.model.ViewGroup hudson.model.View.getOwner() for url=/owner/...
<li>
hudson.util.DescribableList hudson.model.View.getProperties() for url=/properties/...
<li>
BLOCKED: hudson.util.RunList hudson.model.View.getBuilds() for url=/builds/...
<li>
BLOCKED: java.lang.Iterable hudson.model.View.getColumns() for url=/columns/...
<li>
BLOCKED: java.lang.String hudson.model.View.getAbsoluteUrl() for url=/absoluteUrl/...
<li>
BLOCKED: java.lang.String hudson.model.View.getDescription() for url=/description/...
<li>
BLOCKED: java.lang.String hudson.model.View.getNewPronoun() for url=/newPronoun/...
<li>
BLOCKED: java.lang.String hudson.model.AllView.getPostConstructLandingPage() for url=/postConstructLandingPage/...
<li>
BLOCKED: java.lang.String hudson.model.View.getUrl() for url=/url/...
<li>
BLOCKED: java.lang.String hudson.model.View.getViewName() for url=/viewName/...
<li>
BLOCKED: java.lang.String hudson.model.View.getViewUrl() for url=/viewUrl/...
<li>
BLOCKED: java.util.Collection hudson.model.View.getAllItems() for url=/allItems/...
<li>
BLOCKED: java.util.List hudson.model.View.getActions() for url=/actions/...
<li>
BLOCKED: java.util.List hudson.model.View.getAllProperties() for url=/allProperties/...
<li>
BLOCKED: java.util.List hudson.model.View.getApplicablePropertyDescriptors() for url=/applicablePropertyDescriptors/...
<li>
BLOCKED: java.util.List hudson.model.View.getComputers() for url=/computers/...
<li>
BLOCKED: java.util.List hudson.model.View.getQueueItems() for url=/queueItems/...
<li>
BLOCKED: java.util.List hudson.model.View.getVisiblePropertyDescriptors() for url=/visiblePropertyDescriptors/...
<li>
BLOCKED: java.util.List hudson.model.View.getWidgets() for url=/widgets/...
<li>
BLOCKED: hudson.security.Permission hudson.model.View.getItemCreatePermission() for url=/itemCreatePermission/...
<li>
hudson.model.ItemGroup hudson.model.View.getOwnerItemGroup() for url=/ownerItemGroup/...
<li>
hudson.model.View hudson.model.View.getOwnerPrimaryView() for url=/ownerPrimaryView/...
<li>
BLOCKED: java.util.List hudson.model.View.getApproximateQueueItemsQuickly() for url=/approximateQueueItemsQuickly/...
<li>
BLOCKED: java.util.List hudson.model.View.getOwnerViewActions() for url=/ownerViewActions/...
<li>
hudson.model.Descriptor hudson.model.DescriptorByNameOwner.getDescriptorByName(String) for url=/descriptorByName/TOKEN/...
<li>
hudson.model.TopLevelItem hudson.model.View.getJob(String) for url=/job/TOKEN/...
<li>
hudson.model.TopLevelItem hudson.model.View.getItem(String) for url=/item/TOKEN/...
<li>
BLOCKED: java.lang.Object hudson.model.View.getDynamic(String) for url=/dynamic/TOKEN/...
<li>
java.lang.Object hudson.model.View.getDynamic(String,StaplerRequest,StaplerResponse) for url=/TOKEN/...
</ol>
</body></html>
9.440 [id=17] INFO jenkins.model.Jenkins#cleanUp: Stopping Jenkins
9.727 [id=17] INFO jenkins.model.Jenkins#cleanUp: Jenkins stopped
Does anyone know why my test' no longer finds my API? It looks like the plugin was not loaded. If I run mvn hpi:run
, the plugin creates work
in my project's root dir and I can see the plugin installed in work/plugins/
. So, I tested again, this time manually, if the API that caused the previous 404 was accessible and it was.
It should be something related to my local environment or workspace, but I don't know what could have changed since the last time tests worked.
This is the source code of the test
@Rule
public JenkinsRule jenkinsRule = new JenkinsRule();
public void test_ping() throws Exception {
JenkinsRule.WebClient webClient = jenkinsRule.createWebClient();
JenkinsRule.JSONWebResponse response = webClient.getJSON("alm-api/ping");
logJenkinsWebResponse(response);
assertThat(response.getStatusCode(), is(200));
assertThat(response.getJSONObject().get("pong"), notNullValue());
}
private static void logJenkinsWebResponse(JenkinsRule.JSONWebResponse response) {
try {
LOG.info(response.getJSONObject().toString(2,2));
}catch(JSONException ex) {
LOG.info(response.getContentAsString());
}
}
And this's the production code
@Extension
public class AlmApi implements RootAction {
protected static final String ALM_API_NAME = "alm-api";
@Override
public String getIconFileName() {
return null;
}
@Override
public String getDisplayName() {
return null;
}
@Override
public String getUrlName() {
return ALM_API_NAME;
}
@GET
@WebMethod(name = "ping")
public JsonHttpResponse ping() {
JSONObject response = JSONObject.fromObject(new PongDTO(Instant.now()));
return new JsonHttpResponse(response, 200);
}
}
PongDTO: Plain old java object
Observations: I have realised that Jenkins Test, creates target/jenkins-for-test
but everything I see in there is a very small version of Jenkins but I don't find any plugin/
folder. I guess, during the test phase, my extensions get injected into the classloader on-the-fly.
My code is being committed in a GitLab repository every time something in the source code changes. So, I have checked out previous commits (proven to work and pass tests) and tried to run tests again. No test passed. The problem has been the same: 404 Not Found
.
I have also tried ending endpoints with a trailing slash (/
) in all the calls from JUnit tests. It didn't work either.
unit-testing
jenkins-plugins
0 Answers
Your Answer