How to suppress/bypass a static method in a junit test? - java

Let's say I have the following code:
protected int returnFourtyTwo() {
evilMethod(new Object, "");
return 42;
}
protected static void evilMethod(Object obj, String string) {
throw new RuntimeException("This is me being evil.");
}
What I'm trying to do is to run my returnFourtyTwo() method without throwing the runtime exception in my unit test. I've been able to use the suppress() method to bypass class constructors before just fine, but this is the first time I've had to bypass a static method (with more than one argument) in a non-static class. Unfortunately, resources on the topic are a bit scarce.

Your only way out is to mock the static method, as mentioned by #Dave. You can do that with PowerMock.
See Mocking static methods with Mockito.

Depending on how complicated your actual method implementation is, you could separate your return call from your exception throwing - then test on the return call which will not throw the exception. In a lot of cases it's best if strange ints such as 42 have their own variable anyway to explain what it corresponds too - If it is always 42, then it is static and final.
This is what I would do for your exact situation here, but I'm guessing this is a major simple abstraction from your actual problem so you probably still want to mock it as previously suggested.
static final int theAnswerToLife = 42;
protected int returnFourtyTwo() {
evilMethod(new Object, "");
return getTheAnswerToLife();
}
protected int getTheAnswerToLife() {
return theAnswerToLife;
}
protected static void evilMethod(Object obj, String string) {
throw new RuntimeException("This is me being evil.");
}

I don't say it is a good approach, but at least it works and it is not that bad.
you can do this :
create a public method in your inTest class and move your static method call there
in your unit test - you are testing inTest class - you can use a spy instead of mock for your inTest class
just ask unit test to do nothing for that method!
down side? we have a public method instead of private
Example :
I am unit testing the recyclerView Adapter :
I have a logger which has static method call so I moved all logs to a method
fun logMe(message: String) {
MyCrashAnalytics.leaveBreadcrumb(message)
}
and in unit test we have:
val underTest = MyAdapter(....)
then in tests or in setup method we can do this.
val spiedUnderTest = spy(underTest)
doNothing().`when`(spiedUnderTest).logMe(anyString())
Then we are good to go!

In simple you can use #Ignore annotation to your method.

Related

Mockito how to mock a private method [duplicate]

public class A {
public void method(boolean b){
if (b == true)
method1();
else
method2();
}
private void method1() {}
private void method2() {}
}
public class TestA {
#Test
public void testMethod() {
A a = mock(A.class);
a.method(true);
//how to test like verify(a).method1();
}
}
How to test private method is called or not, and how to test private method using mockito?
Not possible through mockito. From their wiki
Why Mockito doesn't mock private methods?
Firstly, we are not dogmatic about mocking private methods. We just
don't care about private methods because from the standpoint of
testing private methods don't exist. Here are a couple of reasons
Mockito doesn't mock private methods:
It requires hacking of classloaders that is never bullet proof and it
changes the api (you must use custom test runner, annotate the class,
etc.).
It is very easy to work around - just change the visibility of method
from private to package-protected (or protected).
It requires me to spend time implementing & maintaining it. And it
does not make sense given point #2 and a fact that it is already
implemented in different tool (powermock).
Finally... Mocking private methods is a hint that there is something
wrong with OO understanding. In OO you want objects (or roles) to
collaborate, not methods. Forget about pascal & procedural code. Think
in objects.
You can't do that with Mockito but you can use Powermock to extend Mockito and mock private methods. Powermock supports Mockito. Here's an example.
Here is a small example how to do it with powermock
public class Hello {
private Hello obj;
private Integer method1(Long id) {
return id + 10;
}
}
To test method1 use code:
Hello testObj = new Hello();
Integer result = Whitebox.invokeMethod(testObj, "method1", new Long(10L));
To set private object obj use this:
Hello testObj = new Hello();
Hello newObject = new Hello();
Whitebox.setInternalState(testObj, "obj", newObject);
While Mockito doesn't provide that capability, you can achieve the same result using Mockito + the JUnit ReflectionUtils class or the Spring ReflectionTestUtils class. Please see an example below taken from here explaining how to invoke a private method:
ReflectionTestUtils.invokeMethod(student, "saveOrUpdate", "From Unit test");
Complete examples with ReflectionTestUtils and Mockito can be found in the book Mockito for Spring.
Official documentation Spring Testing
By using reflection, private methods can be called from test classes.
In this case,
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
// invoke the private method for test
privateMethod.invoke(A, null);
}
}
If the private method calls any other private method, then we need to spy the object and stub the another method.The test class will be like ...
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
A spyA = spy(a);
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
doReturn("Test").when(spyA, "method2"); // if private method2 is returning string data
// invoke the private method for test
privateMethod.invoke(spyA , null);
}
}
**The approach is to combine reflection and spying the object.
**method1 and **method2 are private methods and method1 calls method2.
Think about this in terms of behaviour, not in terms of what methods there are. The method called method has a particular behaviour if b is true. It has different behaviour if b is false. This means you should write two different tests for method; one for each case. So instead of having three method-oriented tests (one for method, one for method1, one for method2, you have two behaviour-oriented tests.
Related to this (I suggested this in another SO thread recently, and got called a four-letter word as a result, so feel free to take this with a grain of salt); I find it helpful to choose test names that reflect the behaviour that I'm testing, rather than the name of the method. So don't call your tests testMethod(), testMethod1(), testMethod2() and so forth. I like names like calculatedPriceIsBasePricePlusTax() or taxIsExcludedWhenExcludeIsTrue() that indicate what behaviour I'm testing; then within each test method, test only the indicated behaviour. Most such behaviours will involve just one call to a public method, but may involve many calls to private methods.
Hope this helps.
I was able to test a private method inside using mockito using reflection.
Here is the example, tried to name it such that it makes sense
//Service containing the mock method is injected with mockObjects
#InjectMocks
private ServiceContainingPrivateMethod serviceContainingPrivateMethod;
//Using reflection to change accessibility of the private method
Class<?>[] params = new Class<?>[]{PrivateMethodParameterOne.class, PrivateMethodParameterTwo.class};
Method m = serviceContainingPrivateMethod .getClass().getDeclaredMethod("privateMethod", params);
//making private method accessible
m.setAccessible(true);
assertNotNull(m.invoke(serviceContainingPrivateMethod, privateMethodParameterOne, privateMethodParameterTwo).equals(null));
You're not suppose to test private methods. Only non-private methods needs to be tested as these should call the private methods anyway. If you "want" to test private methods, it may indicate that you need to rethink your design:
Am I using proper dependency injection?
Do I possibly needs to move the private methods into a separate class and rather test that?
Must these methods be private? ...can't they be default or protected rather?
In the above instance, the two methods that are called "randomly" may actually need to be placed in a class of their own, tested and then injected into the class above.
There is actually a way to test methods from a private member with Mockito. Let's say you have a class like this:
public class A {
private SomeOtherClass someOtherClass;
A() {
someOtherClass = new SomeOtherClass();
}
public void method(boolean b){
if (b == true)
someOtherClass.method1();
else
someOtherClass.method2();
}
}
public class SomeOtherClass {
public void method1() {}
public void method2() {}
}
If you want to test a.method will invoke a method from SomeOtherClass, you can write something like below.
#Test
public void testPrivateMemberMethodCalled() {
A a = new A();
SomeOtherClass someOtherClass = Mockito.spy(new SomeOtherClass());
ReflectionTestUtils.setField( a, "someOtherClass", someOtherClass);
a.method( true );
Mockito.verify( someOtherClass, Mockito.times( 1 ) ).method1();
}
ReflectionTestUtils.setField(); will stub the private member with something you can spy on.
I don't really understand your need to test the private method. The root problem is that your public method has void as return type, and hence you are not able to test your public method. Hence you are forced to test your private method. Is my guess correct??
A few possible solutions (AFAIK):
Mocking your private methods, but still you won't be "actually" testing your methods.
Verify the state of object used in the method. MOSTLY methods either do some processing of the input values and return an output, or change the state of the objects. Testing the objects for the desired state can also be employed.
public class A{
SomeClass classObj = null;
public void publicMethod(){
privateMethod();
}
private void privateMethod(){
classObj = new SomeClass();
}
}
[Here you can test for the private method, by checking the state change of the classObj from null to not null.]
Refactor your code a little (Hope this is not a legacy code). My funda of writing a method is that, one should always return something (a int/ a boolean). The returned value MAY or MAY NOT be used by the implementation, but it will SURELY BE used by the test
code.
public class A
{
public int method(boolean b)
{
int nReturn = 0;
if (b == true)
nReturn = method1();
else
nReturn = method2();
}
private int method1() {}
private int method2() {}
}
Put your test in the same package, but a different source folder (src/main/java vs. src/test/java) and make those methods package-private. Imo testability is more important than privacy.
In cases where the private method is not void and the return value is used as a parameter to an external dependency's method, you can mock the dependency and use an ArgumentCaptor to capture the return value.
For example:
ArgumentCaptor<ByteArrayOutputStream> csvOutputCaptor = ArgumentCaptor.forClass(ByteArrayOutputStream.class);
//Do your thing..
verify(this.awsService).uploadFile(csvOutputCaptor.capture());
....
assertEquals(csvOutputCaptor.getValue().toString(), "blabla");
Building on #aravind-yarram's answer: Not possible through mockito. From their wiki
So what's the OO way of testing private methods? Private methods with complex logic might be a sign that your class is violating the principle of single responsibility and that some of the logic should be moved to a new class.
Indeed, by extracting those private methods to public methods of more granular classes, you can unit test them without breaking the encapsulation of your original class.

JUnits for constructors which uses third party API call

Below mentioned is the class that I need to test:
public class MyClass {
private String key;
public MyClass(Connection con) {
key = ThirdPartyApi.getkey(con);
}
public String getKey() {
return key;
}
}
Now I need to test this constructor, but am unable to mock this Third party API call. And the Test case would be as mentioned below :
public class MyClassTest{
#Test
public void test1(){
MyClass c = new MyClass(dummyconnection);
assertNotNull(c.getKey != null);
}
}
But this case would be giving me an error that ThirdPartyAPI Class is failing as the the connection object is mocked.
So I want to mock this ThirdPartyApi call. Is it possible using Easymock, powermock?
Simple: EasyMock does not support mocking static calls. So you can turn to PowerMock(ito) or JMockit in case you do not want to change your code.
But the better approach would be to understand that using static always leads to tight coupling between your classes, and that you want to make sure that this doesn't affect your ability to unit test your code.
In your case:
public MyClass(Connection con) {
key = ThirdPartyApi.getkey(con);
simply replace that with:
public MyClass(Connection con) {
this (ThirdPartyApi.getkey(con));
}
/** unit testing only */
MyClass(Key key) {
...
And voila, you got a constructor that you can call from your unit test - and now you simply pass a mocked key object. And your tests will no longer execute that static call - because you use the key-taking constructor in all your tests.
But you probably want another test case to make sure that calling the public constructor does what you expect it to do - and that could be to throw an exception because that static call fails.
Beyond that: I fully agree with the comments - the fact that your constructor is doing so much (including static calls) has a certain design smell on it.

Mockito says "Wanted but not invoked" but debugging test jumps into that method

I have to deal with a legacy application that has no tests. So before I begin refactoring I want to make sure everything works as it is.
Now imagine the following situation:
public SomeObject doSomething(final OtherObject x, final String something) {
if(x != null) {
final String = someOtherMethod(x, something);
}
}
protected String someOtherMethod(final OtherObject x, final String something) {
....
}
Now I want to make sure that protected method is called as well
So I did this
#InjectMocks // Yes there is more going on here
private MyTestObject myTestObject;
private MyTestObject spy;
private static final OtherObject VALID_OTHER_OBJECT = new OtherObject();
#Before
public void setup() {
this.spy = Mockito.spy(myTestObject);
}
#Test
public void ifOtherObjectIsNotNullExpectSubMethodToBeCalled() {
myTestObject.doSomething(VALID_OTHER_OBJECT, null);
verify(spy).someOtherMethod(VALID_OTHER_OBJECT, null);
}
I get a failing test and "Wanted but not invoked..." for someOtherMethod().
I jumped right into debug mode and checked. That method is called!
What could be the cause of this? Am I misusing the spy here?
Edit: I want to stretch that I know this is not what you typically test for, especially since someOtherMethod(...) has a non-void return-value here. But imagine the return value was void...
Basically I just want to understand why the spy fails here.
As per its Javadoc, Mockito.spy(object) creates a copy of the passed in object. Calling methods on the original passed in object then does not register on the spy, because the spy instance is not the same object.
Change myTestObject.doSomething(...) to spy.doSomething(...) and it should work.
Alternative (different way to achieve the same thing):
Consider using the #Spy annotation on your myTestObject.
Be sure to add MockitoAnnotations.initMocks(this); to your initialization method (in your junit test).
The #Before and #Mock annotations are useful as well.
I had one object creating another and that other object making calls. So I needed to make that internal object be using the spied reference instead. I used reflection and updated the reference using Whitebox.
TestAddressFragment fragment = spy(new TestAddressFragment());
AddressPresenter presenter = fragment.getPresenter();
Whitebox.setInternalState(presenter, "view", fragment );
Now my fragment could check if its method was called.
verify( fragment ).showAddress(any(), anyBoolean());

Calling a private method inside every JUnit before any test steps

I want to know if there is any technical difference between the following, when writing JUnit tests:
Option 1:
Define a setup method, i.e annotated with #Before, to initialize test fixture state before any #Test method is run.
Option 2:
Define a private method - just a plain old private method without any annotation - that does the same initialization, and make the first line of every #Test method a call to this method. (Ignore the possibility of someone forgetting to call the method in every test. I am looking for technical differences, not human factors)
Example of Option 2:
public class MyTest {
private void runSetupLogic() {
// whatever #Before method would have done
}
#Test
public void testMethod1() {
runSetupLogic();
// test logic
}
#Test
public void testMethod2() {
runSetupLogic();
// test logic
}
}
They are not really exactly the same, but for all intents and purposes either way should be fine. However, if you are interested in the technical analysis then my shaky understanding of the current JUnit 4 code on Github follows:
Here is what seems to be the actual code being ran when you use #Before using the default JUnit 4 runner src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java:
/**
* Returns a {#link Statement}: run all non-overridden {#code #Before}
* methods on this class and superclasses before running {#code next}; if
* any throws an Exception, stop execution and pass the exception on.
*/
protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
Before.class);
return befores.isEmpty() ? statement : new RunBefores(statement,
befores, target);
}
The above calls RunBefores in src/main/java/org/junit/internal/runners/statements/RunBefores.java:
public class RunBefores extends Statement {
private final Statement next;
private final Object target;
private final List<FrameworkMethod> befores;
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
this.next = next;
this.befores = befores;
this.target = target;
}
#Override
public void evaluate() throws Throwable {
for (FrameworkMethod before : befores) {
before.invokeExplosively(target);
}
next.evaluate();
}
The invokeExplosively method definition is in src/main/java/org/junit/runners/model/FrameworkMethod.java:
public Object invokeExplosively(final Object target, final Object... params)
throws Throwable {
return new ReflectiveCallable() {
#Override
protected Object runReflectiveCall() throws Throwable {
return method.invoke(target, params);
}
}.run();
}
which seems to use reflection to invoke the methods annotated with #Before.
Anyway, hope this answer is somewhat correct, but I'm not sure. If anyone has any corrections I can edit them in from the comments. By the way, for reference here is the javadoc for the #Before annotation: http://junit.org/javadoc/latest/org/junit/Before.html
I do not believe so.
However, if you were you implement another function, such as tearDown(), that would function essentially as an #After method, I would argue you might as well use them for readability, for the benefit of other collaborators or maybe even yourself.
The upside to using #Before and #After annotations is the that they avoid having to call a method at the beginning of each unit test, designed to save you the extra maintenance. If for some reason you had forgotten to add the call to your setUp() and/or tearDown() method, who knows what could go wrong.
This is, of course, if you need the EXACT SAME setup before each test. If you envision having a completely different setup for different unit tests, than perhaps you should look at the functionality of the class you are testing and ask yourself if perhaps you could modularize more.
The benifit comes from reporting.
In your method: runSetupLogic()
when ran from the start of a test, is reported within the test. Not as part of the setup and not as part of the initialization.
If the setup method fails, you get an accurate description of what failed... setup vs testing.
The before method allows you to isolate test failures from setup failures and allows the reporting solution to know as well.

Testing Private method using mockito

public class A {
public void method(boolean b){
if (b == true)
method1();
else
method2();
}
private void method1() {}
private void method2() {}
}
public class TestA {
#Test
public void testMethod() {
A a = mock(A.class);
a.method(true);
//how to test like verify(a).method1();
}
}
How to test private method is called or not, and how to test private method using mockito?
Not possible through mockito. From their wiki
Why Mockito doesn't mock private methods?
Firstly, we are not dogmatic about mocking private methods. We just
don't care about private methods because from the standpoint of
testing private methods don't exist. Here are a couple of reasons
Mockito doesn't mock private methods:
It requires hacking of classloaders that is never bullet proof and it
changes the api (you must use custom test runner, annotate the class,
etc.).
It is very easy to work around - just change the visibility of method
from private to package-protected (or protected).
It requires me to spend time implementing & maintaining it. And it
does not make sense given point #2 and a fact that it is already
implemented in different tool (powermock).
Finally... Mocking private methods is a hint that there is something
wrong with OO understanding. In OO you want objects (or roles) to
collaborate, not methods. Forget about pascal & procedural code. Think
in objects.
You can't do that with Mockito but you can use Powermock to extend Mockito and mock private methods. Powermock supports Mockito. Here's an example.
Here is a small example how to do it with powermock
public class Hello {
private Hello obj;
private Integer method1(Long id) {
return id + 10;
}
}
To test method1 use code:
Hello testObj = new Hello();
Integer result = Whitebox.invokeMethod(testObj, "method1", new Long(10L));
To set private object obj use this:
Hello testObj = new Hello();
Hello newObject = new Hello();
Whitebox.setInternalState(testObj, "obj", newObject);
While Mockito doesn't provide that capability, you can achieve the same result using Mockito + the JUnit ReflectionUtils class or the Spring ReflectionTestUtils class. Please see an example below taken from here explaining how to invoke a private method:
ReflectionTestUtils.invokeMethod(student, "saveOrUpdate", "From Unit test");
Complete examples with ReflectionTestUtils and Mockito can be found in the book Mockito for Spring.
Official documentation Spring Testing
By using reflection, private methods can be called from test classes.
In this case,
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
// invoke the private method for test
privateMethod.invoke(A, null);
}
}
If the private method calls any other private method, then we need to spy the object and stub the another method.The test class will be like ...
//test method will be like this ...
public class TestA {
#Test
public void testMethod() {
A a= new A();
A spyA = spy(a);
Method privateMethod = A.class.getDeclaredMethod("method1", null);
privateMethod.setAccessible(true);
doReturn("Test").when(spyA, "method2"); // if private method2 is returning string data
// invoke the private method for test
privateMethod.invoke(spyA , null);
}
}
**The approach is to combine reflection and spying the object.
**method1 and **method2 are private methods and method1 calls method2.
Think about this in terms of behaviour, not in terms of what methods there are. The method called method has a particular behaviour if b is true. It has different behaviour if b is false. This means you should write two different tests for method; one for each case. So instead of having three method-oriented tests (one for method, one for method1, one for method2, you have two behaviour-oriented tests.
Related to this (I suggested this in another SO thread recently, and got called a four-letter word as a result, so feel free to take this with a grain of salt); I find it helpful to choose test names that reflect the behaviour that I'm testing, rather than the name of the method. So don't call your tests testMethod(), testMethod1(), testMethod2() and so forth. I like names like calculatedPriceIsBasePricePlusTax() or taxIsExcludedWhenExcludeIsTrue() that indicate what behaviour I'm testing; then within each test method, test only the indicated behaviour. Most such behaviours will involve just one call to a public method, but may involve many calls to private methods.
Hope this helps.
I was able to test a private method inside using mockito using reflection.
Here is the example, tried to name it such that it makes sense
//Service containing the mock method is injected with mockObjects
#InjectMocks
private ServiceContainingPrivateMethod serviceContainingPrivateMethod;
//Using reflection to change accessibility of the private method
Class<?>[] params = new Class<?>[]{PrivateMethodParameterOne.class, PrivateMethodParameterTwo.class};
Method m = serviceContainingPrivateMethod .getClass().getDeclaredMethod("privateMethod", params);
//making private method accessible
m.setAccessible(true);
assertNotNull(m.invoke(serviceContainingPrivateMethod, privateMethodParameterOne, privateMethodParameterTwo).equals(null));
You're not suppose to test private methods. Only non-private methods needs to be tested as these should call the private methods anyway. If you "want" to test private methods, it may indicate that you need to rethink your design:
Am I using proper dependency injection?
Do I possibly needs to move the private methods into a separate class and rather test that?
Must these methods be private? ...can't they be default or protected rather?
In the above instance, the two methods that are called "randomly" may actually need to be placed in a class of their own, tested and then injected into the class above.
There is actually a way to test methods from a private member with Mockito. Let's say you have a class like this:
public class A {
private SomeOtherClass someOtherClass;
A() {
someOtherClass = new SomeOtherClass();
}
public void method(boolean b){
if (b == true)
someOtherClass.method1();
else
someOtherClass.method2();
}
}
public class SomeOtherClass {
public void method1() {}
public void method2() {}
}
If you want to test a.method will invoke a method from SomeOtherClass, you can write something like below.
#Test
public void testPrivateMemberMethodCalled() {
A a = new A();
SomeOtherClass someOtherClass = Mockito.spy(new SomeOtherClass());
ReflectionTestUtils.setField( a, "someOtherClass", someOtherClass);
a.method( true );
Mockito.verify( someOtherClass, Mockito.times( 1 ) ).method1();
}
ReflectionTestUtils.setField(); will stub the private member with something you can spy on.
I don't really understand your need to test the private method. The root problem is that your public method has void as return type, and hence you are not able to test your public method. Hence you are forced to test your private method. Is my guess correct??
A few possible solutions (AFAIK):
Mocking your private methods, but still you won't be "actually" testing your methods.
Verify the state of object used in the method. MOSTLY methods either do some processing of the input values and return an output, or change the state of the objects. Testing the objects for the desired state can also be employed.
public class A{
SomeClass classObj = null;
public void publicMethod(){
privateMethod();
}
private void privateMethod(){
classObj = new SomeClass();
}
}
[Here you can test for the private method, by checking the state change of the classObj from null to not null.]
Refactor your code a little (Hope this is not a legacy code). My funda of writing a method is that, one should always return something (a int/ a boolean). The returned value MAY or MAY NOT be used by the implementation, but it will SURELY BE used by the test
code.
public class A
{
public int method(boolean b)
{
int nReturn = 0;
if (b == true)
nReturn = method1();
else
nReturn = method2();
}
private int method1() {}
private int method2() {}
}
Put your test in the same package, but a different source folder (src/main/java vs. src/test/java) and make those methods package-private. Imo testability is more important than privacy.
In cases where the private method is not void and the return value is used as a parameter to an external dependency's method, you can mock the dependency and use an ArgumentCaptor to capture the return value.
For example:
ArgumentCaptor<ByteArrayOutputStream> csvOutputCaptor = ArgumentCaptor.forClass(ByteArrayOutputStream.class);
//Do your thing..
verify(this.awsService).uploadFile(csvOutputCaptor.capture());
....
assertEquals(csvOutputCaptor.getValue().toString(), "blabla");
Building on #aravind-yarram's answer: Not possible through mockito. From their wiki
So what's the OO way of testing private methods? Private methods with complex logic might be a sign that your class is violating the principle of single responsibility and that some of the logic should be moved to a new class.
Indeed, by extracting those private methods to public methods of more granular classes, you can unit test them without breaking the encapsulation of your original class.

Categories