Perhaps I have completely fallen short in my search, but I cannot locate any documentation or discussions related to how to write a unit test for a Java class/method that in turn calls other non-private methods. Seemingly, Mockito takes the position that there is perhaps something wrong with the design (not truly OO) if a spy has to be used in order to test a method where mocking internal method calls is necessary. I'm not certain this is always true. But using a spy seems to be the only way to accomplish this. For example, why could you not have a "wrapper" style method that in turn relies on other methods for primitive functionality but additionally provides functionality, error handling, logging, or different branches dependent on results of the other methods, etc.?
So my question is two-fold:
Is it poorly designed and implemented code to have a method that internally calls other methods?
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
This might be a difficult request, but I would prefer for those who decide to answer to not merely re-publish the Mockito verbiage and/or stance on spies as I already am aware of that approach and ideology. Also, I've used Powermockito as well. To me, the issue here is that Mockito developed this framework where additional workarounds had to be created to support this need. So I suppose the question I am wanting an answer to is if spies are "bad", and Powermockito were not available, how is one supposed to unit test a method that calls other non-private methods?
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really. But I'd say that, in this situation, the method that calls the others should be tested as if the others where not already tested separately.
That is, it protects you from situations where your public methods stops calling the other ones without you noticing it.
Yes, it makes for (sometimes) a lot of test code. I believe that this is the point: the pain in writing the tests is a good clue that you might want to consider extracting those sub-methods into a separate class.
If I can live with those tests, then I consider that the sub-methods are not to be extracted yet.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
I'd do something like that:
public class Blah {
public int publicMethod() {
return innerMethod();
}
int innerMethod() {
return 0;
}
}
public class BlahTest {
#Test
public void blah() throws Exception {
Blah spy = spy(new Blah());
doReturn(1).when(spy).innerMethod();
assertThat(spy.publicMethod()).isEqualTo(1);
}
}
To me, this question relates strongly to the concept of cohesion.
My answer would be:
It is ok to have methods (public) that call other methods (private) in a class, in fact very often that is what I think of as good code. There is a caveat to this however in that your class should still be strongly cohesive. To me that means the 'state' of your class should be well defined, and the methods (think behaviours) of your class should be involved in changing your classes state in predictable ways.
Is this the case with what you are trying to test? If not, you may be looking at one class when you should be looking at two (or more).
What are the state variables of the class you're trying to test?
You might find that after considering the answers to these types of questions, your code becomes much easier to test in the way you think it should be.
If you really need (or want) to avoid calling the lower-level methods again, you can stub them out instead of mocking them. For example, if method A calls B and C, you can do this:
MyClass classUnderTest = new MyClass() {
#Override
public boolean B() {return true;}
#Override
public int C() {return 0;}
};
doOtherCommonSetUp(classUnderTest);
String result = classUnderTest.A("whatever");
assertEquals("whatIWant", result);
I've used this quite a quite a bit with legacy code where extensive refactoring could easily lead to the software version of shipwright's disease: Isolate something difficult to test into a small method, and then stub that out.
But if the methods being called are fairly innocuous and don't requiring mocking, I just let them be called again without worrying that I am covering every path within them.
The real question should be:
What do I really want to test?
And actually the answer should be:
The behaviour of my object in response to outside changes
That is, depending on the way one can interact with your object, you want to test every possible single scenario in a single test. This way, you can make sure that your class reacts according to your expectations depending on the scenario you're providing your test with.
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really, and really not! These so called private methods that are called from public members are namely helper methods. It is totally correct to have helper methods!
Helper methods are there to help break some more complex behaviours into smaller pieces of reusable code from within the class itself. Only it knows how it should behave and return the state accordingly through the public members of your class.
It is unrare to see a class with helper methods and normally they are necessary to adopt an internal behaviour for which the class shouldn't react from the outside world.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
In my humble opinion, you don't test those methods. They get tested when the public members are tested through the state that you expect out of your object upon a public member call. For example, using the MVP pattern, if you want to test user authentication, you shall not test every private methods, since private methods might as well call other public methods from an object on which depend the object under test and so forth. Instead, testing your view:
#TestFixture
public class TestView {
#Test
public void test() {
// arrange
string expected = "Invalid login or password";
string login = "SomeLogin";
string password = "SomePassword";
// act
viewUnderTest.Connect(login, password);
string actual = viewUnderTest.getErrorMessage;
// assert
assertEqual(expected, actual);
}
}
This test method describes the expected behaviour of your view once the, let's say, connectButton is clicked. If the ErrorMessage property doesn't contain the expected value, this means that either your view or presenter doesn't behave as expected. You might check whether the presenter subscribed to your view's Connect event, or if your presenter sets the right error message, etc.
The fact is that you never need to test whatever is going on in your private methods, as you shall adjust and bring corrections on debug, which in turn causes you to test the behaviour of your internal methods simultaneously, but no special test method should be written expressly for those helper method.
Related
I am currently working my way through he book "Growing Object Oriented Design - guided by tests". The authors are the creators of JMock which is used within the book. Since Mockito currently has the most expressive (readable) API I am using Mockito instead of JMock.
For most examples this worked great so far with much less code. It is interesting though to see how the APIs evolved over the time and frameworks (JMock -> EasyMock -> Mockito) and still base on the same concepts.
Anyway: I need to verify that a mock-method is called at the time when a another objects state has a certain value.
public class TestSomething{
private MyMockedInterface mock;
private States state;
#Test
public void testMethod()
{
// I need something like
when(state.equals(value)).verify(mock).method()
sut.doSomething();
}
}
Unfortunately when(T methodCall) cannot handle object comparison. A assertEquals after sut.something() wont help me here because the state might have changed within doSomething several times.
I am quite sure there must be a way to address this. Would be strange if the old JMock had a feature Mockito doesnt :-) ... I just cant find it.
What you need is something called an Answer - this is an object that wraps a little chunk of code that will run when your method is called. The syntax for using an Answer is described at http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#11
In your Answer, you can use asserts to check that the state of the other objects is what you need it to be. Then at the end, you can do your verify, just to ensure that the method was called.
I'm asking because I'm trying to use a mocking framework (Mockito) which does not allow you to mock static methods. Looking into it I've found quite a few blog posts saying that you should have as few static methods as possible, but I'm having difficulty wrapping my head around why. Specifically why methods that don't modify the global state and are basically helper methods. For instance I have a class called ApiCaller that has several static methods. One of the static method's purpose is to execute an HTTP call, deal with any custom issues our server might have returned (ex. user not logged in) and return the response. To simplify, something like:
public class ApiCaller {
...
public static String makeHttpCall(Url url) {
// Performs logic to retrieve response and deal with custom server errors
...
return response;
}
}
To use this all I have to do is call ApiCaller.makeHttpCall(url)
Now I could easily make this a non static method like:
public class ApiCaller {
...
public String makeHttpCall(Url url) {
// Performs logic to retrieve response and deal with custom server errors
...
return response;
}
}
and then to use this method call new ApiCaller().makeHttpCall() but this just seems like extra overhead. Can anyone explain why this is bad and if there is a better solution to making the methods non static (other than just removing the keyword) so that I can stub out these methods using the mocking framework?
Thanks!
The problem with static methods is they're very hard to fake when they're not relevant to the system you're trying to test. Imagine this code:
public void systemUnderTest() {
Log.connectToDatabaseForAuditing();
doLogicYouWantToTest();
}
The connectToDatabaseForAuditing() method is static. You don't care what this method does for the test you want to write. But, to test this code now you need an available database.
If it were not static the code would look like this:
private Logger log; //instantiate in a setter AKA dependency injection/inversion of control
public void systemUnderTest() {
log.connectToDatabaseForAuditing();
doLogicYouWantToTest();
}
And your test would be trivial to write without a database now:
#Before
public void setUp() {
YourClass yourClass = new YourClass();
yourClass.setLog(new NoOpLogger());
}
//.. your tests
Imagine trying to do that when the method is static. I can't really think of a way except for modifying the logger to have a static variable called inTestMode that you set to true in the setUp() to make sure it doesn't connect to a database.
It is less modular. Instead you should define an interface ApiCaller with an instance method makeHttpCall() so that you can define separate implementations in the future.
In the very least you will always have 2 implementations of an interface, the original and the mocked version.
(Note: there are some mocking frameworks that allow you to mock static methods)
As an addendum, while this may not be the case in your specific application, typically the use of static methods is indicative of a larger design oversight. Designing for modularity and reuseability should be prevalent throughout your application, because even though you don't need it right now you may need it in the future, and it's much harder and much more time consuming to change things after the fact.
PRIVATE Static helper methods are not bad, in fact, they are actually preferred at the large corporation where I work. And I use Mockito with them all the time, accessed from the methods that call the static helper method.
There is a slight difference in how the compiler treats a static helper method. The byte code created will result in an invokestatic instruction, and if you remove the static the result will be one of the other instructions, like invokespecial. The difference there being that invokestatic loads the class to access the method, where invokespecial pops the object off the stack first. So there might be a slight performance advantage (maybe not).
That you can't mock them easily when you need to pretty much answers your own question.
Particularly when it's something as shown: making an HTTP call is expensive, and doing that for unit testing your code makes no sense–save that for integration testing.
Unit tests require known responses (and response codes) from HTTP calls, something that you can't do if you're calling someone else's service, using a network you don't control.
This explanation seems to me very straight forward, and easy to understand.
Declare utility methods as static, often makes your code easier to understand, which is a good thing.
But, there is a serious limitation to this approach though: such methods / classes can't be easily mocked.
So if a helper method has any external dependency (e.g. a DB) which makes it - thus its callers - hard to unit test, it is better to declare it non-static.
This allows dependency injection, thus making the method's callers easier to unit test.
Source: https://softwareengineering.stackexchange.com/a/111940/204271
I have a question regarding unit testing.
I have a function which does the following thing:
void myFunction(List<MyClass> myList) {
// 1. Sort the list
// 2. Post Process the list
}
Now I want to test this function. But the problem is I should not test these two things at the same time. I am therefore thinking to extract the "Post Process the list" part as a separate function.
But the problem is the task of "Post Process the list" is only used by myFunction and I want to make it private to the class.
If I make it private I won't be able to test it from outside.
What is the general rule of this kind of scenario? Must I change a private function to public only for testing?
Or if there are any other patterns I should use?
Many thanks
The test method only needs to be package-local.
You can call private methods using reflections and there are mocking libraries which allow you to test private methods. But I would just make it package-local as it shows the method is access from elsewhere in the package (which it is either way)
As others have said, you don't need to make the method public, just package visible.
Google Guava has a #VisibleForTesting annotation which is meant for situations like this. You put this annotation on a method, just to document that the reason that the method isn't private is only for testing. The annotation doesn't do anything, it's just meant as a warning for programmers that they shouldn't call it from outside the class. (Some static code checking tool could in principle check if methods with this annotation aren't called from anywhere except inside the class or from test code).
Ofcourse it's kind of ugly to have to modify your code to do this just for testing. If you want to avoid this, you can do tricks with reflection to call the private method:
public class Sandbox {
public static void main(String[] args) throws Exception {
Example e = new Example();
Method m = Example.class.getDeclaredMethod("myFunction", List.class);
m.setAccessible(true);
m.invoke(e, Arrays.asList("one", "two", "three"));
}
}
class Example {
private void myFunction(List<String> data) {
System.out.println("Hey, what are you doing! " + data);
}
}
In general, you should always test the functionality through public methods. If there is some functionality in private methods, which cannot otherwise be tested well enough, that's an indication that the method has a responsibility which should be moved to its own class (this also helps to achieve high cohesion). Then that newly extracted class can be tested directly though its public methods.
Another vote for package-local. Just ensure that your newly exposed method is clearly named and documented so that in future it is not called inappropriately.
It depends.
Dose the sub routine contains common behavior that you should extract ?
Take your first sub routine as example. If you're not sorting your list by Comparator<T>, you should refactor it, then test that Comprartor<T> class instead of your private method. If Post process are actually some algorithm or common business logic, you might want to refactor it using Strategy pattern then test those class you just extract.
The point is, if a private method is complex enough to require a unit-test, then chance is probably you should not put them there, otherwise you should just test through it's public API.
It's a legacy system, and it will take forever to refactor that method.
check Bad Smells in Code : Long method for long method refactor, Method Object is a good strategy for things like this.
It's fine, I just want to test them.
Then you can test through Java reflection API, and I believe there are some mocking framework like PowerMock can also help you.
Below things you may consider for testing a private method.
1.create public method written only for the purpose of testing. (or)
2.create nested class for testing (or)
3.use reflection to test it.
useful link,another useful link from stackoverflow
I typically consider private methods to be part of the method under test. They typically consist of code that has been moved out of the original method to make it leaner and shorter, and more modular. However from a test perspective you would be testing the same code if you moved the content of the private method into your method under test.
The question of trying to isolate the return values of private methods to simulate various conditions is is often valid though. I think its' part of the larger question of how to write testable code.
One approach with very little overhead is to rely on basic overriding of methods. You can make your private methods protected virtual instead, and override them in your test:
Here's an example of that too :
http://www.unit-testing.net/CurrentArticle/How-To-Remove-Data-Dependencies-In-Unit-Tests.html
The example is C#, but the concept applies to all object oriented languages
Lets say we have method to test in class A that calls method from class B. To test it we created mock for B and then verify if it was called. Is verify(...) enough for unit test or I need assert actual result of tested method?
Below is simplified example to clarify my concern:
public class StringWriterATest {
StringWriterB b = mock(StringWriterB.class);
#Test
public void stringWriterATest() {
StringBuffer sb = new StringBuffer();
StringWriterA a = new StringWriterA();
a.stringWriterB=b;
a.append(sb);
ArgumentCaptor<StringBuffer> argument = ArgumentCaptor.forClass(StringBuffer.class);
verify(b).append(argument.capture());
assertEquals("StringWriterA", ((StringBuffer)argument.getValue()).toString());
//do we really need this or above is enough for proper unit test of method a.append(sb);
//assertEquals("StringWriterA_StringWriterB", sb);
}
}
public class StringWriterA {
public StringWriterB stringWriterB;
public void append(StringBuffer sb) {
sb.append("StringWriterA");
stringWriterB.append(sb);
}
}
class StringWriterB {
public void append(StringBuffer sb) {
sb.append("StringWriterB");
}
}
Regards,
Max
There is never a need to mock a return value and verify an object at the same time.
Consider this:
StringWriterA is the class under test. Therefore you'll definitely want to use assertions to verify the behavior of this class. In order to do this, you mock out a dependency, StringWriterB.
You do not want to test StringWriterB in your test of StringWriterA, therefore any assertions of StringWriterB interactions in your test are in the wrong place.
You must assume that StringWriterB is behaving as expected. You either want to verify that StringWriterA called StringWriterB correctly (using verify()) or you want to mock its expected behavior and mock the return values.
If you mock, then the verify is implicit since the mocked return value will not be returned if the method is not called.
In your case, StringWriterA.append() does not return any value, so only a verify is even possible. That StringWriterB.append() also works should have a similar verify test in a stringWriterBTest of its own.
Note: It's nice to be explicit with tests. Since test methods are never called outside of a framework, there is never a need to type them out, so you can have much longer method names than in production code methods. A nice convention is:
<underTest>Should<Expected>[When]<Condition>()
i.e.
stringWriterAShouldAppendConstantAndDelegateToStringWriterB()
stringWriterAShouldThrowNullPointerExceptionWhenNullArgument()
When you have test failures in your build (continuous integration), then you don't have to hunt down what went wrong, the method name appears right by the failure and you can read it to know exactly what behavior must be fixed.
In your example, StringWriterB stores no state and the append method could easily be static. In that case then the call is purely a side effect and does not need to be tested.
However, I suspect your real code is much more complex. If there is a of another object accessing StringWriterB then you maye want to mock it out in case there are unexpected calls to it. You also may want to add the verify of B if you expect it to be expanded in the future -- possibly storing state from the append call and having accessors.
One thing to consider is what the purpose of the call to StringWriterA.append() is. If it's job is to append the string StringWriterAStringWriterB then that is what you should be testing and a mock is not necessary. How StringWriterA accomplishes that task is immaterial. If, however, part of its job is to also call the StringWriterB.append() method then a mock may will be necessary unless you want to test StringWriterB in A's test.
My rule of thumb WRT mocks is to use real objects until the wiring for the objects I'm not directly testing gets too hairy or too brittle. If I feel like a good portion of my tests are in actuality testing other objects then mocks would be a good idea.
First of all try to show somebody the test you wrote. It is hard to read in my opinion. You can't really tell from it what behaviour you are testing. A brief intro for you how to make it a bit more readable can be found here How to Write Clean, Testable Code .
Using argument captors is also a smell. Some examples how to avoid it can be found on this tdd blog.
To answer you question, verify is used to verify interactions between classes. It is used to drive the design of your code. The result (if needed) should be specified by a when or given at the beginning of your test.
Further information how to drive your design with mocks (when, given, verify, ...) and how mocks are different to stubs can be found here: Mocks are not stubs. That example uses JMock not Mockito for defining mocks, but it is very similar (it is about the concepts, not the details of implementation and libraries you use).
This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 5 years ago.
JUnit will only test those methods in my class that are public. How do I do junit testing on the ones that are not (i.e., private, protected)?
I can test them by not using junit, but I was wondering what the junit standard method was.
One school of thought about unit testing says that you should only be able to test public methods, because you should only be unit-testing your public API, and that by doing so, you should be covering the code in your non-public methods. Your mileage may vary; I find that this is sometimes the case and sometimes not.
With that said, there are a couple of ways to test non-public methods:
You can test protected and package-scope methods by putting your unit tests in the same package as the classes they're testing. This is a fairly common practice.
You can test protected methods from unit tests in another package by creating a subclass of the class under test that overrides the methods you want to test as public, and having those overridden methods call the original methods with the super keyword. Typically, this "testing subclass" would be an inner class in the JUnit TestCase class doing the testing. This is a little bit more hacky, in my opinion, but I've done it.
As with many unit testing problems, testing private methods is actually a design problem in disguise. Rather than try to do anything tricky to test private methods, when I find myself wishing to write tests for private methods I take a minute to ask myself, "How would I need to design this so I could test it thoroughly through public methods?"
If that doesn't work, JUnitX allows testing private methods, although I believe it is only available for JUnit 3.8.
When you write a JUnit test, you have to do a subtle mind shift: "I'm a client of my own class now." That means private is private, and you only test the behavior that the client sees.
If the method really should be private, I'd consider it a design flaw to make it visible just for the sake of testing. You've got to be able to infer its correct operation based on what the client sees.
In the three years that have passed since I originally wrote this, I've started approaching the problem slightly differently, using Java reflection.
The dirty little secret is that you can test private methods in JUnit just as you would public ones, using reflection. You can test to your heart's content and still not expose them as public to clients.
The simplest solution is to put the JUnit tests in the same package (but different directory) and use default (i.e. package-private) visibility for the methods.
Another more complicated approach is to use reflection to access private methods.
If you have a significant amount of logic buried under relatively few "Public" entry points, you are probably violating the Single Responsibility Principle. If possible, you'll want to refactor the code into multiple classes, ultimately leading to more "Public" methods from which to test.
Here is the "probably shouldn't do it this way" method that everyone else keeps harping at you about. I think it's certainly within the realm of possibility that there are reasons for doing it this way, though. The following code will access a private field, but the code for a private method is nearly identical.
public void testPrivateField() throws InterruptedException {
Class<ClassWPrivateField> clazz = ClassWPrivateField.class;
try {
Field privateField = clazz.getDeclaredField("nameOfPrivateField");
privateField.setAccessible(true); // This is the line
// do stuff
} catch(NoSuchFieldException nsfe) {
nsfe.printStackTrace();
fail();
} catch(IllegalAccessException iae) {
iae.printStackTrace();
fail();
}
}
I've come across the same issue, and the "if it needs to be private it probably should be refactored" doesn't sit right with me.
Suppose you have sort of functionality that you want to separate out in some way internal to the class. For example, suppose I have something like this:
public class HolderOfSomeStrings{
private List<String> internal_values;
public List<String> get()
{
List<String> out = new ArrayList<String>();
for (String s:internal_values)
{
out.add(process(s));
}
return get;
}
private static String process(String input)
{
//do something complicated here that other classes shouldn't be interested in
}
}
The point here is that junit forces me to make process public, or at least protected, or to put it in it's own utility class. But if it's some sort of internal logic of HolderOfSomeStrings, it's not at all clear to me that this is correct—it seems to me that this ought to be private, and making it more visible gums up the code in some way.
I nearly always use Spring in my Java projects and, as such, my objects are built for dependency injection. They tend to be fairly granular implementations of public interfaces that are assembled within the application context. As such, I rarely (if ever) have the need to test private methods because the class itself is small enough that it simply isn't an issue.
Even when I don't use Spring I tend to adopt the same practices of assembling small and simple objects into larger and larger abstractions, each of which is relatively simple but made complex by the aggregated objects.
In my experience, having the need to unit test private methods is an indicator that what you're teesting could (and should) be simplified.
That being, if you still really feel the need:
Protected methods can be tested by subclasses;
Package private methods can be tested by putting the unit tests in the same package; and
Private methods can be unit tested by providing, for example, a package private factory proxy method. Not ideal but private does mean private.
You usually don't test private methods because they can only (normally) be tested indirectly through another public method. When you're test driving and make private methods then they are usually a result of an "extract method" refactoring and are already by then tested indirectly.
If you are concerned about testing a private method with lots of logic then the smartest thing you could do is to move that code into another class in a public method. Once you've done that, the previous method that used this code can have it's testing simplified by having the functionality provided by a stub or a mock.
To borrow a thought from Andy Hunt, even your private methods must have some side effect that you're interested in. In other words, they must be called from some public method and perform an interesting task that causes the state of your object to change. Test for that state change.
Suppose you have public method pubMethod and private method privMethod. When you call pubMethod, it in turn calls privMethod to perform a task (perhaps parsing a String). The pubMethod then uses this parsed String to set member variables' values in some way or to influence its own return value. Test by watching for the desired effect on pubMethod's return value or on member variables (possibly by using accessors to get to them).
DP4j Jar
For testing private methods we need to use reflection and its pointed in all answers.
well now this task is simplified with help of Dp4j jar.
Dp4j analyzes your code and automatically generates the Reflection API code for you.
Just add dp4j.jar to your CLASSPATH.
Dp4j.jar contains Annotation Processors, they will look for the methods in your code that are annotated with #Test JUnit annotation.
Dp4j analyze the code of those methods, and if it finds that you are illegally accessing private methods, it will replace your invalid private method reference with equivalent code that uses Java's Reflection API.
Get More details here
You can use TestNG instead of JUnit, which doesn't care about the method being private or public.
Use reflection as above to test private methods.
If we are following TDD we should test private methods given that TDD implies that there would be no surprises later.
So one should not wait to finish his public method to test privates.
And this helps in more granular regression testing upon re factoring.
Look for "PrivateAccessor.invoke". My code imports it from "junitx.util", but I don't know where it came from.
In agreement with just about every post--you should probably refactor and probably not test private except through public, just wanted to add a different way to think about it...
Think of your class itself as a "Unit", not a method. You are testing the class and that it can maintain a valid state regardless of how it's public methods are called.
Calling private methods can destroy the encapsulation and actually invalidate the tests.
As kind of an offshoot of this, and I'm not sure where everyone comes down on the whole "polyglot programming" issue, but Groovy tests are runnable in Junit, and ignore the whole public/non-public issue. Side note, it was officially classified as a "bug", but when they tried to fix it, there was such a storm kicked up about it that it was put back as it was originally.
I absolutely agree with #duffymo that code should be tested from the client's view ( though he says he quit thinking this way). However, from this point of view, private vs others have different meanings. Client of a private method is the class itself so I prefer testing them through the external (public/package-protected) API. However, protected and package-protected members are there for external clients, so I test them with fakes which inherit the owning class or which reside in the same package.