-
Notifications
You must be signed in to change notification settings - Fork 470
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
PowerMockito can mock static JRE methods in JUnit but not in Spock #1014
Comments
I still found no explanation and also no workaround with package de.scrum_master.test
import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate
import org.spockframework.runtime.Sputnik
import spock.lang.Specification
import java.sql.Date
import static org.powermock.api.support.membermodification.MemberMatcher.method
import static org.powermock.api.support.membermodification.MemberModifier.stub
@RunWith(PowerMockRunner)
@PowerMockRunnerDelegate(Sputnik)
@PrepareForTest(ClassCallingStaticJREMethods)
class SpockTest extends Specification {
def testUUID() {
given:
final String id = "493410b3-dd0b-4b78-97bf-289f50f6e74f";
UUID uuid = UUID.fromString(id)
stub(method(UUID, "randomUUID")).toReturn(uuid)
ClassCallingStaticJREMethods underTest = new ClassCallingStaticJREMethods()
expect:
underTest.genUUID() == id
}
def testSQLDate() {
given:
def date = new Date(1971 - 1900, 5 - 1, 8)
stub(method(Date, "valueOf", String)).toReturn(date)
ClassCallingStaticJREMethods underTest = new ClassCallingStaticJREMethods()
expect:
underTest.genDate("1998-12-20") == date
}
} Please note that I need to prepare the class under test rather than the JRE classes with the static methods for test via |
Actually I found out that the same problem occurs in JUnit tests written in Groovy when using PowerMock. So this is not a Spock issue per se. While for JUnit tests I can just annotate the classs or methods using PowerMock with I have documented my findings and provided sample code in Powermock issue #1008. Maybe the Spock and PowerMock maintainers can talk to each other in order to find a way to avoid this problem. Maybe the Groovy people at Spock have ideas for the Java people at PowerMock how to implement this in a way to make it compatible with Groovy. |
This cannot be solved on either side unless Powermock would add explicit Groovy support which is probably very unlikely. Powermock uses custom classloaders for non-system classes and if you The same rewriting happens with the test class itself. PowerMock rewrites the byte code of the test class to not call the actual system class but to record / verify the calls. Only if you use Due to that it works as expected if you And as Spock is not going to support One can try to use it on the feature method as some feature methods will work with |
Thanks for the good explanation and for confirming my educated guesses. Besides, the existing tickets to support mocking for static methods and final classes/methods in Spock for non-Groovy code would still be my favourites because not to need PowerMock at all when using Spock would be desirable. |
I agree. |
Dear Björn, the following rant is not directed personally at you and I don't think that you are one of the Spock maintainers (feel free to correct me if I am wrong). But I like to get something off my chest. I don't like to be unfriendly or exude a sense of entitlement, but today I am not in a super friendly mood either, so let me be blunt: If every time I got 1 Euro for "feel free to implement a PR" as an answer to a bug report or feature request, I would be a rich man today. I have not been a professional developer for a long time, last time I got money for coding was more than 15 years ago. I am an agile coach who still codes a little bit in his spare time for fun or uses his coding skills for coaching developers when necessary. Still if I can I contribute to OSS projects, be it via PR (if I am technically capable of it), documentation contribution or just by filing and re-testing bugs etc. I do know that OSS also depends on third-party contributions. But I do think that this kind of answer is just unnecessary and evasive. Whether OSS maintainers like it or not, together with the software they created they also took a certain degree of responsibility and ought to live up to it. A killer phrase like "PRs are welcome" in order to avoid having to maintain the project is just not very helpful. To mere users who clearly lack the technical capability to contribute more than trivial bugfixes this feels like they are being mocked by the superior tech buffs. Look, I speak some Java and am quite familiar with Groovy as a Spock user, but unless a maintainer takes a few hours to explain the internals of Spock and Groovy meta programming to me, it is completely unrealistic that I can implement that myself. If it was that simple, I am pretty sure a Spock maintainer would have done it already because many people ask for it. I know because I answer a lot of Spock questions on StackOverflow (which is also a kind of contribution to the project because the maintainers can concentrate more on the product instead of user support). BTW, in the past I offered to OSS maintainers several times to spend some time on introducing me into the project's source code and other internals in order to help me get up to speed in becoming a co-maintainer or contributor, but usually they say they are too busy. But at the same time they are also too busy to fix bugs and implement features. So which should it be? It is like saying: "I don't have time to sharpen my saw/axe because I am so busy cutting down trees." |
Correct. :-)
Yeah, same for me, unfortunately it doesn't work that way. :-D Be assured, I don't take it as a personal attack. But then I always remind myself, that this is not fair either and decide to either provide the PR or just ignore the statement.
And imho even recommending a software is important contribution as is reporting bugs, contributing documentations and so on. Be assured that I totally understand you and totally agree.
Here I have to disagree.
Sure, but it is still better to release the OSS, even if they don't have much time to maintain, as it is OSS and any member of the OSS community can help maintaining. You have to consider that most OSS is also created and maintained by the authors in their sparse spare time and their is most often not some company behind that pays them to maintain the software full-time.
This has nothing to do with Groovy at all.
Just that many people ask for something doesn't mean it gets implemented soon,
Yes, this is sad and often reading and understanding the source yourself is the only way to get up and running which can sometimes be frustrating and confusing. |
If anyone still needs mock static methods, have a look at spock-mockfree |
Spock now supports static mocks via mockito and the Spock API |
I sometimes help people on StackOverflow or development teams I am coaching as an Agile Coach with test automation. Usually I introduce them to Spock + Geb and tell them to take their fingers off of PowerMock and similar frameworks. Instead I am telling them to refactor for better testability.
Anyway, I do know how to use PowerMockito from Spock and for the most part it works nicely, but in the past and then again lately I ran into problems when trying to do something like the following JUnit test in Spock:
So far, so good. Now let's convert that test into a Spock test:
If you want a repeatable build, put the class under test into
src/main/java
and the tests undersrc/test/java
andsrc/test/groovy
, respectively. This is the standard Maven project layout. Then build using this POM (I condensed a POM from bigger project into this one):The Maven build
mvn clean test > build.log 2>&1
says:Here is an archive with all source code files quoted above incl. Maven POM:
Spock_PowerMockStaticJREMethods.zip
My actual question is not primarily a request to the Spock maintainers to make Spock compatible with PowerMock (even though that would be nice) but to explain what is happening here and how I can work around it. I assume the problem is related to Groovy code transformations taking place in Spock tests or maybe something about delegates, meta classes or how methods are discovered and called in general. The whole area of Groovy delegates, meta classes etc. is not my area of expertise, so I am asking, sorry.
Is there any way I can stop Spock from actually evaluating the original static method and instead doing whatever ought to be done in order to get these calls under PowerMock's control?
The text was updated successfully, but these errors were encountered: