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
Restore ability to mock internal classes #326
Comments
@SuppressWarnings is not available at runtime (it has "source" retention), so it wouldn't be an option. I will wait a few months to see if more users want the ability to have mockups for internal classes. |
Thanks for keeping an open mind - and for explaining SuppressWarnings. I really appreciate the tool. |
Inline with this topic I have a question: |
Mocking of protected methods continues to be supported by @mocked. On Mon, Sep 5, 2016 at 10:59 AM, hamid-nazari notifications@github.com
|
Hi. Regarding the decision to warn when using the MockUp API for internal classes, I understand your reasoning. However, I hope you consider that the MockUp API has great value even when @mocked and the Expectations API aren't being used. To give an example, in my company we are doing a lot of API testing using JUnit with a custom test framework that loads API requests and responses from config files and performs a direct call to the Spring methods to process that request. Each request config file specifies not just the payload but other parameters, including which mocks to use for that request. So based on the individual test case config, these mocks (which are based on MockUp) are dynamically loaded and instantiated for the duration of that request. So while we make heavy use of MockUp in these particular tests, we don't actually use the Expectations API at all in these tests. (Of course, in other kinds of tests, we make use of both.) I think this flexibility of JMockit is one of the great things about it. I understand that you don't want to encourage bad behavior for the most common use cases, but I think that keeping this kind of powerful flexibility is valuable. |
We recently ran in the same issue (Invalid mock-up for internal class...), while testing the upgrade of jmockit in our codebase. What is considered as internal class? Every class, which is not part of an external library? |
Yes, classes not from external libraries are "internal". Note the "Invalid mock-up for internal class" is just a warning, not an I will probably add a system property to allow for internal mock-ups, to be On Mon, Sep 12, 2016 at 10:10 AM, Manuel notifications@github.com wrote:
|
Version 1.28 will add a system property "allowed-internal-mockups", which can list the names of internal mockup classes. For these, the warning won't be shown. |
How do you use this property? I set the property and added the names of the classes to it, but I'm getting the Warning and an IllegalArgumentException as well. |
I don't want to rage here, just a little thinking about the direction jmockit is going. My problem is that the real world is not just about good code. One is often facing a ugly old codebase where you need to fix that one special bug and then leave the rest behind. Mocking final Singletons even with SingletonHolders was no problem. Mocking out pretty big private methods as they add nothing to the code i wanted to test, but just increase the number of But the last releases seem to kill one feature after another to force the users to write tests that apply to your or Martin Fowlers (academic?) vision of mock tests. For me personally i was switching from 1.23 to 1.27 and had to change ca. 40% of my very small jmockit testbase. I dont want to know what happens if there where hundereds of them (just dopping them and leaving untested code behind? not realy). Thank you for reading |
So far, absolutely no concrete evidence has been shown that mockups for internal classes are useful in good tests. From the looks of it, no evidence will be shown. So, most likely the warning will become an exception in version 1.30 or 1.31. |
Wouldn't all these people wanting to use them qualify them as useful? Many arguments have been given, and I think it's a little silly to ask for "concrete evidence" when testing philosophy is obviously a matter of taste. I don't think sticking so closely to some ideological notion of "good testing" is really that productive, if doing so harms testing in practice. In practice, lots of people end up doing useful testing even without having the privilege of being able to write ideal tests in an ideal code base. I know that personally I don't always have the time, freedom or ability to dig in and rework existing code bases when writing tests, for many good and valid reasons. In an ideal world we'd all love to be writing only good code and testing it with good tests. In practice, people often end up writing good tests for bad code. This is where JMockit shines, and I really don't understand why these features are being removed. If your code base is easy to test, great. And making a code base easier to test in a noble endeavor. But why punish those people stuck with difficult and hard to test code bases? Why punish the person who wants to get their tests up and working quickly so they know their code works, then dig in and refactor it all later? Why break thousands of working test cases because a person wants to upgrade for a bug fix? It's fine to have a testing philosophy, but why not give the users of JMockit the freedom to decide on their own philosophy too? |
Why don't you add a mode? |
@nebel @numeralEasy You know what, I think you're right! I was just thinking about this whole issue of "preventing misuse/abuse of the mocking/faking APIs" today... It sure would be nice to get rid of all that validation code, making the JMockit codebase smaller, simpler, faster, and avoiding the occasional bug or unexpected problem arising from said code. Also, in the end people will always find ways to write bad tests. (I recently had the opportunity to examine one such test suite of 1500+ tests which used Mockito in a terrible way - it could just as well have used JMockit or any other mocking library.) So, instead of the validations, I am going to just add some advice in the documentation. This should also free more time for me to work in the coverage tool, which still needs major improvements. |
Hi @rliesenfeld , I just upgrade jmockit to 1.29 and found all my test case that mock private method failed. After I read the release note, I found:
After I read your comments in some issues items, I understand you want to do so because you want people test base on the behavior but not implementation detail. For this point, I am 200% agree with you.However, please do not assume that, for every java projects, a "unit being tested" means one java class. I focused on enterprise application development(use Spring mainly). In my project, most of the times, the business logic is not that simple, For example, we have one Service (I mean the service objects in Spring) object to handle order creation. The order is complicated. We need to do validation 1, validation 2, validatioan 3. Then, save data come from UI into different tables. Generate audit log base on data from UI. Call workflow engine to submit order. Now, our practice is, we create a public method createOrder(). createOrder() call private methods validate1(), validate2(), validate3(), saveDate() and generateAuditLog(). If I use jmockit 1.29 to test this program, I should not mock any private methods in internal classes. Which means, when I want to test createOrder(), I only have 2 options:
So, the testing approach I want is:
Conclusions:
|
I moved from 1.24 to 1.29 and I am getting the same InvalidArgumentException and warning. This issue has been closed, how was it resolved and what version of JMockit is it resolved in? Just to clarify why I am mocking an internal class. The class that is being mocked is the entry point for network communication with the application that is under test. In the test suite, data received on the socket is mocked and injected into the application by mocking this class. |
This should be resolved in 1.30 which comes out on the 18th. I'm in the
same boat as you. If you look in the release notes on the main site you'll
see which release fixes which issue. I'm stuck on 1.23 and anticipate
having to rewrite every single Expectation block when I finally upgrade to
1.30. I really thing this backlash would have been avoided had jmockit used
a semantic versioning scheme of Major.Minor.Patch where Patch is for bug
fixes, Minor is for adding new features and maybe deprecations, and only
Major should introduce breaking changes. The way things are now each 1.x
release is a Major release by most API standards.
…On Wed, Dec 14, 2016, 12:28 PM eoghanoh1 ***@***.***> wrote:
I moved from 1.24 to 1.29 and I am getting the same
InvalidArgumentException and warning.
This issue has been closed, how was it resolved and what version of
JMockit is it resolved in?
Just to clarify why I am mocking an internal class. The class that is
being mocked is the entry point for network communication with the
application that is under test. In the test suite, data received on the
socket is mocked and injected into the application by mocking this class.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#326 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABlGHcKBhrIzvn5z_AEaNuTeBpswosXyks5rICcrgaJpZM4J0ZBf>
.
|
1.31 resolves a lot of these types of blockers for me. It's much more
forgiving than 1.24-1.29 Most of the breaking changes now have to do with
redundant recordings, so fixing those will actually simplify your tests.
There is a bug that will prevent you from upgrading Gradle without
upgrading jmockit as well. Rogerio might have strong opinions, but he has
listened to the community. I would still recommend someone fork 1.23 and
backport bug fixes if you must stay on it.
…On Fri, Feb 3, 2017, 11:06 AM Dell ***@***.***> wrote:
same here pegged to 1.23 due to the large volume of changes required to
work around all this
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#326 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABlGHTPq_wkrViQv7R0oClB5bUS90LGyks5rY1B5gaJpZM4J0ZBf>
.
|
cool thanks just noticed 1.30 available in netbeans and this does indeed fix things for me |
I second wanting private mocking like this. 'Good' tests may not need to internals, but you often have to write tests for code you didn't write where you actually need to validate something specific got hit, or need to mock a specific internal to make the test remotely reasonable. Not all codebases are sane. There's no good reason to deny users the ability to do this. "Not a good practice" is subjective and defendant upon factors outside of your control, and it is best to leave it to the programmers discretion. Make a PrivateExpectations or something, so code analysis tools can mark it as a smell. |
As of JMockit 1.27 mocking of classes from the same codebase produces an error saying it is not allowed and mocking private methods produces an error. I see you closed issue 324 so this is an enhancement.
Can you remove that check or put in a way to disable it - maybe with SuppressWarnings? I find it useful to mock out methods that setup FileWriters and replace them with mock methods that setup StringWriters so no files are written during test runs. I could probably use Deencapsulation to modify it or make the method protected and then use a subclass, but I don't always have direct access to the class - e.g. I am testing some class that uses a helper object that has a FileWriter.
Thanks.
The text was updated successfully, but these errors were encountered: