Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't mock up sh when called from class method #451

Open
joanayma opened this issue Nov 25, 2021 · 7 comments
Open

Can't mock up sh when called from class method #451

joanayma opened this issue Nov 25, 2021 · 7 comments

Comments

@joanayma
Copy link

joanayma commented Nov 25, 2021

I'm testing a library (var/test.groovy) that uses a class (src/foo/MyClass.groovy) using a Jenkinsfile (resources/Jenkinsfile) loaded in test (tests/PipelineTest.groovy) (I simplified the example). I'm having issues passing the script block to a method of the class.

Issue example: https://github.com/joanayma/jenkinsPipelineUnit-issue-451

the error is:

$ gradle clean build test --info
[...truncated]
myPipelineTest > should run FAILED
    groovy.lang.MissingMethodException: No signature of method: com.lesfurets.jenkins.unit.declarative.StageDeclaration.sh() is applicable for argument types: (LinkedHashMap) values: [[returnStdout:true, script:docker wait mock-container]]
    Possible solutions: is(java.lang.Object), use([Ljava.lang.Object;), any(), post(groovy.lang.Closure), when(groovy.lang.Closure), tap(groovy.lang.Closure)
[...truncated]

I've been using this passing script object to class method several times and works fine in Jenkins. Actually script.docker mocks up docker just fine. I also tried to mock up the 'sh' command as shown but no luck.

Should I implement this in a different way? How can I mock up a method when it's on the StageDeclaration? Thanks.

@joanayma joanayma added the bug label Nov 25, 2021
@nre-ableton
Copy link
Contributor

nre-ableton commented Nov 25, 2021

You are calling helper.registerAllowedMethod('sh', [Map.class], null), but you don't call sh with mapped arguments, you call it with a string (hence the exception). So the call in your setup method should be helper.registerAllowedMethod('sh', [String], null).

@joanayma
Copy link
Author

Sorry, I was a bit sleepy and missed that I'm calling the sh with options. I updated the run method in the example. Thanks.

@joanayma
Copy link
Author

I added an reproducible example here: https://github.com/joanayma/jenkinsPipelineUnit-issue-451 and updated issue description.

@joanayma
Copy link
Author

@nre-ableton any idea what to do? Should I implement something different in the above class?

@nre-ableton
Copy link
Contributor

@joanayma If you could make a PR which had a failing test case, that would be really convenient. Then I could take the PR and find the source of the problem more easily, since I could more easily debug it with the framework. The repo you created is nice, but I haven't had time to get around to forking it and playing around with it.

@nre-ableton nre-ableton removed the bug label Jan 11, 2022
@sergemat
Copy link

I have the same issue. Consider this scenario:

  • ClassA has methodA that calls sh.
  • ClassB has method that create new instance of ClassA and calls it methodA.
  • The test for ClassB can load ClassB and call its methods.
  • However, sh call in methodA fails with this error
    No signature of method: ClassA.sh() is applicable for argument types: (String) values: ...

The code for classes is below:

class ClassA {
 def methodA {
    sh 'boo'
  }
}

class ClassB {
 def methodB {
    new ClassA().methodA()
  }
}

As you can see above, ClassA is loaded using "new" statement and not "load" statement.
It seems that when ClassB is loaded by ClassA, its methods are not intercepted as with the loadScript() approach.
Loading ScriptB with loadScript() before the test makes no difference because ClassA create new instance of ClassB that is not the same as the instance loaded by loadScript() during test initialization.

@sergemat
Copy link

I was able to work around this issue by adding this code to setUp() in the test class.

InterceptingGCL.interceptClassMethods(ClassA.metaClass, helper, binding)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants