I have a private method whose invocation I want to test without caring about the arguments. I want to test if it was called at all or not.
MyClass.java
public void doStuff(){
unload(args);
}
private void unload(List<String> args) {
//
}
So I used following:
MyClasstest.java
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
verifyPrivate(myClass, times(1)).invoke("unload",any(List.class));
// verifyPrivate(myClass, times(1)).invoke("unload",any()); //same result with this
This test fails with following exception:
Wanted but not invoked com.MyClass.unload(
null );
However, there were other interactions with this mock .......
(actual values with which it was called)
Can verifyPrivate be called with only actual arguments & not with any()?
Here is a working example of what you are trying to do:
You might just missing the #PrepareForTest annotation, which has to point to the correct class. If your class is an external one use #PrepareForTest(MyClass.class), the example below shows it with an internal class.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClassTest.class)
public class MyClassTest {
static class MyClass {
public void doStuff(){
unload(null);
}
private void unload(List<String> args) {
}
}
#Test
public void test() throws Exception {
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
PowerMockito.verifyPrivate(myClass, Mockito.times(1)).invoke("unload", Mockito.any());
}
}
Note that you should consider whether you really want to do this in a UnitTest. Normally your UnitTest should not be concerned about whether a private method is used or not, it should be focused on verifying that the correct result is returned or the correct object state is reached.
By adding knowledge about the internal behaviour of the class into it, you test is tightly coupled to the implementation which might not be a good thing.
I have this original code:
public SomeClass(int parameter) {
this.someProperty = parameter;
this.apiObject = new SomeApiClass(someProperty);
for(i=0; i < 2; i++)
apiObject.setApiProperty(i, "Hello World");
}
The code works perfectly fine. But the problem arises when I try to test the same.
#Mock
private SomeApiClass someApiClass;
private SomeClass someClass;
#Before
public void setUp() throws Exception {
someClass = new SomeClass(3);
}
#Test
public void shouldCreateSomeClass() {
verify(someApiClass, times(2)). setApiProperty(anyInt(),anyString());
}
I understand why this test wouldn't pass. This would work if I change the constructor to this:
public SomeClass(int parameter, SomeApiClass someApiClass) {
...
}
How do I test the original code if I do not want to inject SomeApiClass to the constructor and also can't afford to provide any getters in it.
PS: Please ignore typos in the code. Typed it on the fly.
It's good to think about testability when you design your class and also to differentiate parameters and dependencies.
Dependencies are objects that the class will rely on to get its work done. They generally don't change throughout the lifecycle of the dependee object.
Parameters are more localized than dependencies. They are expected to change in between calls to the methods of the object.
In the original code, it looks like the work done in the constructor for SomeClass should really go inside a method:
public class SomeClass {
public void doWork(int parameter) {
//
}
}
Inside the method, if you are only interested in instantiating SomeApiObject with the parameter, then why not follow the Law of Demeter and pass in directly SomeApiObject as a parameter:
public void doWork(SomeApiObject someApiObject) {
//
}
Then the consumer does the work:
someClass.doWork(new SomeApiObject(3));
and it can be tested by passing in a mocked SomeApiObject as a parameter:
//act
someClass.doWork(mockedSomeApiObject);
//assert
verify(mockedSomeApiObject).someVerification();
However, if you want a combination of parameters and dependencies you can use a Factory as a dependency:
public class SomeClass {
private final SomeApiObjectFactory someApiObjectFactory;
public SomeClass(SomeApiObjectFactory someApiObjectFactory) {
this.someApiObjectFactory = someApiObjectFactory;
}
public void doWork(int parameter) {
SomeApiObject someApiObject = someApiObjectFactory.create(parameter);
//etc
}
Then you can now test the class since you have a way to supply mocks on which behaviour can be verified:
SomeApiObject mockSomeApiObject = Mockito.mock(SomeApiObject.class);
when(mockSomeApiObjectFactory.create(anyInt()).thenReturn(mockApiObject);
Aside from all of that there are ways of using Powermockito to test your original class as it is without alteration but these are not ideal and it is best to refactor if possible so you can use plain Mockito to test. This will give you good OO habits. Good luck!
What is the recommended pattern to modify constants for unit tests? This is currently what I've used for some time and today I realized it's flawed.
Assume my class looks like this
class Foo {
private static final int MAX_TIME = Integer.getInteger("myProp", 1000);
...
}
The fact that I use a VM property is not only to modify it in a unit test. It is because I want it to be immutable from the actual code and I don't want to pollute a constructor with it since it is an implementation detail.
So, in production I want a timeout of 1 second; however that's too long for unit tests so I do this
class FooTest {
#Before
public void setUp() {
System.setProperty("myProp", "50");
}
#Test
public void testThatAssumesTimeoutOf50() { ... }
}
This worked fine for a long time until today I finally added a BarTest like this
class BarTest {
Foo mockFoo = mock(Foo.class); //actually done in a #Before method in the real code
}
Now what this created is that my tests fail or pass depending on the order of execution. If Foo is tested first, the test that assumes a testing timeout of 50ms passes. But if Bar is tested first then this makes Foo to be loaded due to the mock so MAX_TIME takes the default value of 1000 and then when BarTest ends and FooTest starts, the test that assumes a testing timeout of 50ms now fails.
The easiest way is probably to remove the final keyword. This will let you change the value after class loadtime.
Since you set and get the value across many different classes, and possibly packages, you should probably add a getter and setter. If you need to change this value across packages, then it will have to be public.
class Foo{
public static int getMaxTime(){
return MAX_TIME;
}
public static void changeMaxTime(int timeout){
//validation logic goes here
this.MAX_TIME = timeout;
}
Then, in your test classes, you should save the old value in the #BeforeClass or #Before phase, change it to whatever you want, and then restore the old value in the #AfterClass or #After phase.
Since it looks like you do this across many test classes, it might be best to actually make your own Test Rule:
public class TimeoutRule extends ExternalResource {
private final int oldTimeout, newTimeout;
public TimeoutRule(int timeout){
this.oldTimeout = Foo.getMaxTime();
this.newTimeout = timeout;
}
#Override
protected void before() {
}
#Override
protected void after() {
//restore old timeout
Foo.setMaxTimeOut(oldTimeout);
}
}
Then in your test code:
class FooTest {
#Rule
public TimeoutRule timeoutRule = new TimeoutRule(50);
#Test
public void testThatAssumesTimeoutOf50() { ... }
}
That code will reset the timeout to 50 ms and then restore it to the original value after every test. If you wanted to only do it once per test class, use #ClassRule instead (and make the field static)
Is it possible to control the value of the global variable in the class that I test?
The global variable is used in a private method, so I use a public method (in the same class) to pass through it.
How can I say that mListValService != null?
public class Myclass {
//my global variable
private ListValServiceRemote listValService = null;
public String getCodeValeurRef(Long idValeur) {
return getListValService().getRlvCode(idValeur);
// I want 100% coverage on this method so i have to change the value
// of mListValService.
private ListValServiceRemote getListValService() {
if (listValService == null) {
listValService = ServiceGetter.getListValService();
}
return listValService;
}
ReflectionTestUtils from spring-test might be a solution to access the field value. You can also use plain old reflection, add getter/setter to the field or make the field protected and put the test in the same package as the tested class.
Sample test:
public class MyclassTest {
private MyClass myClass;
#Before
public void setup() {
this.myClass = new MyClass();
}
#Test
public void testGetListValServiceWhenFieldIsNull() {
assertNotNull(this.myClass.getListValService());
}
#Test
public void testGetListValServiceWhenFieldIsNotNull() {
final ListValServiceRemote lvsr = new ListValServiceRemote();
ReflectionTestUtils.setField(this.myClass, "listValService", lvsr);
assertSame(lvsr, this.myClass.getListValService());
}
}
First of all, seems you are not using IoC technique, and hence you have problems while unit testing the code.
Secondly, a private is the private, don't test it. Your code should be tested and covered only by using public methods. If some code is not reachable via public interface, then it is not reachable at all. Why do you want to test it then?
This particular code could be easily 100% covered if you just invoke getCodeValeurRef() twice. And also if you would have listValService == null, it will cause NullPointerException failing the test anyway, so an assert is not required.
You could expose the getListValService() method as package-private, then call it in a test. You can confirm the same value is returned each time:
#Test
public void sameListValTest() {
Myclass foo = // construct this somewhow
assertTrue(foo.getListValService() == foo.getListValService());
}
This will give you 100% coverage without fiddling with a private field.
Or you could just call getCodeValeurRef() twice in your test to achieve the same results. Anything that causes the getListValService() to execute twice will give you 100% coverage. Exposing it as package-private allows you to verify that you are re-using the same field, not creating one each time (if that's important).
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.