Let's say that there just so happens to be an existing long private method (one of which i'm not allowed to refactor into smaller pieces at this stage in the development process) but i really want to write a couple of regression-protection unit test for it, just for now.
i just heard of this #VisibleForTesting annotation, but am not too sure of its benefits and gotchas. Previously, i had always been marking things with #Deprecated and comments to try and make it VERY CLEAR like:
... some code ...
// ====================================== TESTING USE ONLY BELOW ======================================
#Deprecated // TESTING ONLY, DO NOT USE!
boolean testGiveAccessToSomethingPrivate() {
// call some private method and get the results
}
it seems that whenever i mark something as #VisibleForTesting it seems to expose the method for realz, without any indication to the user of the API that this method was only meant for testing... (whereas if i mark the method with #Deprecated, most IDEs will put a strike-through that warns other developers to not accidentally use the test method for their actual code
#Deprecated
When the method is marked #Deprecated, programmers use this method will know maybe this method will be removed, different behavior ... in future version. And if that happen, your code will be broken and you will rework. So, they should use this function very carefully or should replace by other function. (often programmer who made this api will make another similar function without deprecated for you to use).
#VisibleForTesting
You have learnt public private protected ... and you use it well. But in real world, everything not as our imagination. For example, your class have a private variable, and you want to test this variable, how can?
class SimpleClass() {
private int a;
public simpleMethod() {
if (a < 0) {
// do something
} else {
// do another thing
}
}
}
One way is changing scope of variable a to package level, because your test file will be same package with file to be tested. But another programmer jumps into and they will ask their self: "Why someone put modifier of a is package level? I think private level is better". (of course, they don't know or don't mind reading your test code because life is so busy). So you will have a way for their to know by using #VisibleForTesting. They read this and Google and know: "Ahhhh, I understood. He want this variable is testable".
That's a very short story about those two annotations. The similar is: They don't change the way your code run. Not change anything but notify for other people to know something. Very famous annotation every Java Developer knew and similar is #Override
The difference is: #Deprecated for someone using your code, and #VisibleForTesting for someone reading your code. Let make life's programmer easier in both case.
Hope this help :)
Related
I know how to access private variables, but I have the following class that I'm trying to test:
ProcessStatusResult:
#Getter
class ProcessStatusBody {
public ProcessStatusBody(ProcessStatus status) {
this.status = status;
}
ProcessStatus status;
}
#Getter
public class ProcessStatusResult {
ProcessStatusBody body;
...
public ProcessStatusResult(ProcessStatus status) {
body = new ProcessStatusBody(status);
...
}
}
In my test, I need to get the ProcessStatus inside ProcessStatusBody to validate it, but I have no idea how to do that.
Is there a way to use reflection (or some other method) to access this without having to add a getter in ProcessStatusResult for the sake of the test alone?
There are broadly speaking 3 different ways to tackle this problem.
The common way - (ab) use package private.
It's common to stick (unit1) tests in the same package as the code it tests. Different 'source root', same package. You'd have:
src/main/java/com/foo/Whatever.java
src/test/java/com/foo/TestWhatever.java
When you do this, your test code can just 'see' all package private stuff (because, same package).
Some projects would like to highlight this a bit and have an annotation that indicates 'this item is package private for the sake of test code; we would have made it private otherwise', and if you really want to go all-out, you add linter tools that detect any attempt to interact with entities so marked from other source files in the same package (not the test code) and flag it as an error.
These tools are, in my experience, unfortunately not commonly used and I'm not readily aware of linter tools that do this. A somewhat common annotation for this is guava's #VisibleForTesting. It doesn't do anything except serve as documentation (for now - one could write a linter tool that actually checks for style violations, of course).
The uncommon way, reflection and mocking
Test frameworks can do this but it severely hampers productivity. If you want to access your status variable, all you need to do is type body. and hit CTRL+SPACE or equivalent in your IDE and it'll be shown right there, you can just select it, you can CMD+click once you type or auto-complete it to be taken straight to its definition, and if you typo the name, your IDE will red-wavy-underline it.
Replace body.status with something like reflect.getField(body, "status", ProcessStatus.class); and it's a heck of a mess. It's long, ugly, mismatches generics to types (what if status is of type List<String>? List<String>.class isn't valid java. You could use reflection hackery to allow you to assign reflect.getField to anything you please, but now you have no type safety. If you mess up the type, you won't know until you run it. If you mess up the generics, you may not ever know, ouch.
Hence, this isn't great either, and is consequently not used often.
The nuanced way: That's not how it works.
private perhaps just means private. It's not meant for consumption by anything 'external to the source' file and that includes the unit tests. No source file consists solely of 100% private everything - there is some API you're supposed to plug into from 'outside', and test code can get at everything except private (so, package private, protected, and public is all accessible by test code). Test the public API parts, don't test the private stuff - after all, the normal idea behind private is that you're free to mess with these as much as you please, change what they do, change their signatures, all you need to check is what impact that has based solely on what else is in this source file you are looking at.
There is benefit in not having to extend that to: "... oh and you also need to revisit all the unit tests that interact directly with this".
Make an actual public-ish API (package private if you wish, but you write it with the actual intent that code from outside this source file will want to use this feature) and test that. Or, if truly this field is not a detail that even other source files in the same package are meant to know about then do not test it - it's too fine grained a test.
There are upsides and downsides to testing at such incredibly fine grained levels. Generally, that level of fine-grainedness makes tests simpler and more 'localized' (any error the tests catch will be pointing right at the actual problem), but going that deeply means you need a heck of a lot of tests, most tests turn into the trivial, and it creates significant resistance to refactoring - after all, even a simple refactor requires modifying a lot of tests as well. You're also risking "Copycat syndrome", where the same programmer writes both the unit test and the code that is being tested, and any mental error is therefore likely to exist in both, thus making the test completely useless.
A solution to copycat syndrome is to disentangle the writing of the test with the writing of the code. This is obviously easy to do when one person writes the test and another writes the implementation, but you can do it on your own - just make sure there's time and a 'mental break' between writing tests and writing the implementation, enough to prevent your brain from replaying the exact same reasoning when writing either (which is the likely path to making the same error twice in a row without realizing).
However, when you disentangle like this, it becomes really weird and unwieldy to test with the granularity of 'testing the private stuff' - testing like this tends to follow the notion of 'there is some API spec of sorts and that is what we test', and private stuff by definition isn't part of such a spec.
Whether you like to write the tests first, or the tests last - the same principle applies. It's bizarre to write tests and, during the writing of them, already start cooking up the private methods that you envision will be required to implement it: That's not your 'job' as test writer.
It's similarly strange (slightly less so, perhaps) to write tests that test implementation choices.
SO isn't intended for opinion so I won't spend more than two sentences on it, but my strong suggestion is that third option. private means: Not to be tested directly.
1) Really, any test where the scope of what it tests is clearly restricted to some 'unit' of code that in your project's code style rules requires being in a single package. The two concepts ('what do I stuff in packages' and 'what does this test' need to at least line up, or 'what do I test' needs to be more finegrained than that). In other words, integration tests that test the entire project don't get to use this strategy at all, but then if those are testing private variables, I'm pretty sure you're doing something wrong.
Well, here you have some working code using reflection:
// Assuming you have the objects
ProcessStatusResult processStatusResult = new ProcessStatusResult(new ProcessStatus());
ProcessStatusBody processStatusBody = processStatusResult.getBody();
try {
// The status field, you know the name, right?
Field privateField = ProcessStatusBody.class.getDeclaredField("status");
// Set the accessibility to true since it is not visible
privateField.setAccessible(true);
// Here we go
ProcessStatus status = (ProcessStatus) privateField.get(processStatusBody);
System.out.println(status);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
// do something
}
Sorry, I didn't realize you said: "Is there a way to use reflection..."
I recently refactored some code which converted a public method that was only being used in conjure with another public method, into one call.
public class service() {
public String getAuthenticatedUserName() {
return SecurityContext.getName();
}
public getIdentityUserIdByUsername(String username) {
return db.getUser(username).getId();
}
}
which was being utilised in a few other classes as service.getIdentityUserIdByUsername(service.getUsername()), which seemed redudant. A new method was created combining the two calls.
public getIdentityUserId() {
return getIdentityUserIdByUsername(getUsername());
}
The getIdentityUserIdByUsername() is still being utilised in other classes without the need for getUsername(). However, the getUserName() method is no longer used in other classes.
My example is much simpler than the implementation, the method has test coverage that is a bit awkward to do (mocking static classes without Powermock and a bit of googling etc). In the future it's likely we will need the getUsername() method, and the method will not change.
It was suggested in code review that the getUsername() method should now be private due to it not being called anywhere else. This would require the explicit tests for the method be removed/commented out which seems like it would be repeated effort to rewrite or ugly to leave commented out code.
Is it best practice to change the method to private or leave it public because it has explicit coverage and you might need it in the future?
Is it best practice to change the method to private or leave it public because it has explicit coverage and you might need it in the future?
IMO, you are asking the wrong question. So called "best practice" doesn't come into it. (Read the references below!)
The real question is which of the alternatives is / are most likely to be best for you. That is really for you to decide. Not us.
The alternatives are:
You could remove the test case for the private method.
You could comment out the test case.
You could fix the test case so that it runs with the private version of the method.
You could leave the method as public.
To make a rational decision, you need to consider the technical and non-technical pros and cons of each alternative ... in the context of your project. But don't be too concerned about making the wrong decision. In the big picture, it is highly unlikely that making the wrong choice will have serious consequences.
Finally, I would advise to avoid dismissing options just because they are "code smell". That phrase has the same issue as "best practice". It causes you to dismiss valid options based on generalizations ... and current opinions (even fashions) on what is good or bad "practice".
Since you want someone else's opinion ("best practice" is just opinion!), mine is that all of the alternatives are valid. But my vote would be to leave the method as public. It is the least amount of work, and an unused method in an API does little harm. And as you say, there is a reasonable expectation that the method will be used in the future.
You don't need to agree with your code reviewer. (But this is not worth making enemies over ...)
References:
No Best Practices by James Bach
There is no such thing as "Best Practices": Context Matters. by Ted Neward.
It can make sense to want to test private methods. The industry standard way to do this, which has quite some advantages, is this:
Ensure that the test code lives in the same package as the code it tries to test. That doesn't mean same directory; for example, have src/main/java/pkg/MyClass.java and src/test/java/pkg/MyClassTest.java.
Make your private methods package private instead. Annotate them with #VisibleForTesting (from guava) if you want some record of this.
Separately from this, the entry space for public methods (public in the sense of: This is part of my API and defines the access points where external code calls my code) is normally some list of entrypoints.. if you have it at all. More often there is no such definition at all. One could say that all public methods in all public types implicitly form the list (i.e. that the keyword public implies that it is for consumption by external code), which then by tautology decrees that any public method has the proper signature. Not a very useful definition. In practice, the keyword public does not have to mean 'this is API accessible'. Various module systems (such as jigsaw or OSGi) have solutions for this, generally by letting you declare certain packages as actually public.
With such tooling, 'treeshaking' your public methods to point out that they need no longer be public makes sense. Without them... you can't really do this. There is such a notion as 'this method is never called in my codebase, but it is made available to external callers; callers that I don't have available here, and the point is that this is released, and there are perhaps projects that haven't even started being written yet which are intended to call this'.
Assuming you do have the tree-shaking concept going, you can still leave them in for that 'okay maybe not today but tomorrow perhaps' angle. If that applies, leave it in. If you can't imagine any use case where external code needs access to it, just delete it. If it really needs to be recovered, hey, there's always the history in version control.
If the method is a public static then you can leave it as is because there is no impact of it being public. It is aside effect free method, it being exposed will never cause any harm.
If it is a object level public method then -
1) Keep it if it is like an API. It has well defined input, output and delivers a well defined functionality and has tests associated with it. It being public doesn't harm anything.
2) Make it private immediately if it has side effects. If it causes others methods to behave differently because it changes the state of the object then it is harmful being public.
I wanted to test the specification of the class in a way that when an annotation is removed from the getter method the tests should fail and warn that specification of class has changed.
class SomeBean{
#XMLElement(name = "name")
public String getName(){
return name;
}
}
class SomeBeanUnitTest{
#Test
public void test_getNameMustHaveAnnotation(){
Method getNameMethod = SomeBean.class.getDeclaredMethod("getName", new Class<?>[]{});
assertNotNull(getNameMethod.getAnnotation(XmlElement.class));
}
}
Do testing methods for declared annotations is a proper way to check the specification of class? As this will make the tests more brittle, but it will provide proper feedback that the annotation was removed from the getter method. Is it advisable to write such tests?
This condition is even covered in Integration test, but the feedback provided by Integration will not point out the problem.
It depends.
It depends on how important/crucial to your application working that annotation is. This of course may sound very general as one might assume that every piece of code is important for application to function properly.
I'll give you example from my own backyard - we use annotation testing to verify whether methods of classes implementing certain interface are marked with [Transaction] attribute. Why is this important? Beacuse it's very easy to:
forget to mark method
remove attribute accidentally
become a victim of unfortunate merging accident
What is worse, when the method isn't marked with [Transaction], at first glance nothing bad happens. Application runs and functions properly. But as you might have probably guessed, such method doesn't run in transaction - which once in a while might cause critical error which is extremly hard to track. Cost of writing such test / benefit is very low.
Now, how important is #XMLElement for proper workings of your application and how critical errors it may cause was it missing is for you to judge. When in doubt, weight the cost vs benefit. As for me, if I could replace any non deterministic, hard to track/debug error with automated test (even costly and brittle one), I'd do that anyday.
I'm testing a function that takes several paramters and on the basis of their values calls different private methods.
I want to check that the function always call the right private method.
Since I know what the private methods will do I can check the final result but it would be more convenient to be able to check directly if the right function was called, because I have already tested the private methods.
Is there a way to replace a privae method with a stub?
Yes, there are mocking libraries that let you do this. One is PowerMock. From their private method tutorial, you need something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyUnit.class)
public class TestMyUnit {
#Test
public void testSomething() {
MyUnit unit = PowerMock.createPartialMock(MyUnit.class, "methodNameToStub");
PowerMock.expectPrivate(unit, "methodNameToStub", param1).andReturn(retVal);
EasyMock.replay(unit);
unit.publicMethod(param1);
EasyMock.verify(unit);
}
}
However, I really disagree with this practice myself. Your unit test should test inputs, outputs, and side effects, and that's it. By ensuring that a private method is called correctly, all you're doing is preventing your code from being easily refactored.
In other words, what if down the road you want to change how your unit does its job? The safe way to do this is to make sure the code is under (passing) tests, then refactor the code (potentially including changing which internal methods are called), and then run the tests again to make sure you didn't break anything. With your approach, this is impossible because your tests test the exact implementation, not the behaviour of the unit itself. Refactoring will almost always break the test, so how much benefit is the test really giving you?
Most often you would want to do this because you're actually considering those privates a unit unto themselves (this sound like you, since you say you are testing those private methods directly already!). If that's the case, it's best to extract that logic into its own class, test it, and then in the remaining code interact with a mock/stub version of that new unit. If you do that, your code has a better structure and you don't need to fall back on the voodoo magic that is PowerMock. A fantastic reference to do these kinds of refactorings is Michael Feathers' Working Effectively with Legacy Code.
You may check java instrumentation to do so
As one of solution can be used proxy from inner classes. You need add inner class inside every your class which must be tested.
But it is not very good solution for big product project. its require create addition script for remove generated classes from your release files(jar/war).
But more easier way will be used PowerMock as wrote in comments bellow(or upper :)) - http://code.google.com/p/powermock/wiki/MockPrivate
Would it be possible to provide the class in question with another object, to which the private methods are moved and made public? In that case, it would be easy to create a test dummy for that interface.
If calling the right "private method" has no observable outside result, are you sure you want to test this? Maybe shouldn't.
If the end result is the same regardless of whether the private method gets called, and you still want to observe its invocation, you could make the method public and move it to its own class, and mock that class. Then you could verify (using Mockito or a similar framework) whether your method is being called.
Code coverage tools do this kind of thing by re-writing the bytecode before the tests are actually run. So, it's got to be possible, but it's non-trivial.
Update: writing a unit test that requires that the "right" private method be called kind of makes the job of refactoring a real pain because then you have to re-write all your tests. That kind of defeats the purpose of the tests.
One of the built-in Checkstyle checks is RequireThis, which will go off whenever you don't prepend this. to local field or method invocations. For example,
public final class ExampleClass {
public String getMeSomething() {
return "Something";
}
public String getMeSomethingElse() {
//will violate Checkstyle; should be this.getMeSomething()
return getMeSomething() + " else";
}
}
I'm struggling with whether this check is justified. In the above example, the ExampleClass is final, which should guarantee that the "right" version of getMeSomething should be invoked. Additionally, there seem to be instances where you might want subclasses to override default behavior, in which case requiring "this" is the wrong behavior.
Finally, it seems like overly defensive coding behavior that only clutters up the source and makes it more difficult to see what is actually going on.
So before I suggest to my architect that this is a bad check to enable, I'm wondering if anyone else has enabled this check? Have you caught a critical bug as a result of a missing this?
The RequireThis rule does have a valid use in that it can prevent a possible bug in methods and constructors when it applies to fields. The code below is almost certainly a bug:
void setSomething(String something) {
something = something;
}
Code like this will compile but will do nothing except reassign the value of the method parameter to itself. It is more likely that the author intended to do this:
void setSomething(String something) {
this.something = something;
}
This is a typo that could happen and is worth checking for as it may help to prevent hard to debug problems if the code fails because this.something is not set much later in the program.
The checkstyle settings allow you to keep this useful check for fields while omitting the largely unnecessary check for methods by configuring the rule like this:
<module name="RequireThis">
<property name="checkMethods" value="false"/>
</module>
When it comes to methods this rule has no real effect because calling this.getMeSomething() or just getMeSomething() has no effect on Java's method resolution. Calling this.getSomethingStatic() still works when the method is static this is not an error, it is only a warning in various IDEs and static analysis tools.
I would definitely turn it off. Using this.foo() is non-idiomatic Java, and should therefore only be used when necessary, to signal that something special is going on in the code. For example, in a setter:
void setFoo(int foo) {this.foo = foo;}
When I read code that makes gratuitous use of this, I generally mark it up to a programmer without a firm grasp on object-oriented programming. Largely because I have generally seen that style of code from programmers that don't understand that this isn't required everywhere.
I'm frankly surprised to see this as a rule in CheckStyle's library.
Calling with "this." does not stop the invocation from calling an overridden method in a subclass, since this refers to "this object" not "this class". It should stop you from mistaking a static method for an instance method though.
To be honest, that doesn't sound like a particularly common problem, I personally wouldn't think it was worth the trade-off.
Personally I wouldn't enable it. Mostly because whenever I read code I read it in an IDE (or something else that does smart code formatting). This means that the different kind of method calls and field accesses are formatted based on their actual semantic meaning and not based on some (possibly wrong) indication.
this. is not necessary for the compiler and when the IDE does smart formatting, then it's not necessary for the user either. And writing unnecessary code is just a source of errors in this code (in this example: using this. in some places and not using it in other places).
I would enable this check only for fields, because I like the extra information added by 'this.' in front of a field.
See my (old) question: Do you prefix your instance variable with ‘this’ in java ?.
But for any other project, especially legacy ones, I would not activate it:
chances are, the keyword 'this.' is almost never used, meaning this check would generate tons of warnings.
naming overrides (like a field and a method with a similar name) are very rare due to the current IDE flagging by default that code with a warning of their own.