Testing a method which calls private void method inside using mockito - java

I want to test a method which internally calls a void method.
Below is the code
public String process(MKSConnectionParams mksConnectionParam, IProgressMonitor progressMonitor) throws Exception {
if (null != progressMonitor) {
progressMonitor.beginTask("Starting the creation of report", 100);
}
if (null == mksConnectionParam) {
initialize(MksLibFactory.getDefault());
}
else {
initialize(mksConnectionParam, MksLibFactory.getDefault());
}
--------------
}
public void initialize(MKSConnectionParams mksConnectionParam, IMksLibrary mksLibDefault) throws Exception {
paramMKSConnectionParams = mksConnectionParam;
GlobalConstants.hostName = paramMKSConnectionParams.hostname;
GlobalConstants.port = String.valueOf(paramMKSConnectionParams.port);
try {
localISi = mksLibDefault.getSi(paramMKSConnectionParams);
localIIm = mksLibDefault.getIm(paramMKSConnectionParams);
}
catch (MksLibException | AuthenticationError e) {
throw e;
}
ProjectInfo prjInfo = localISi.getProjectInfo(pathToPj);
projRevCmd = prjInfo.getConfigPath().getConfigPath() + "#b=" + projectRevision;
}
I am writing mockito test case for process() method. Testing is getting failed when initialize(mksConnectionParam, MksLibFactory.getDefault()) is called. It is because in the process we are calling real mks connection and I am passing dummy user name and password.
We aren't able to mock this initialize method. Is there any way to do this?
Small pseudocode would be of great help.
Earlier I had initialize method as private. Would changing it to public make any difference?

There are several ways to test this scenario, and different people would advocate different approaches, mostly based on personal preference.
Notice that testing this, will require changes in the code of the class you're testing (I believe you neglected to mention its name). There is one exception, and that's if you're using PowerMock. I won't go into the details here, but you find out more on how to incorporate it into your mockito code here.
Back to regular testing methods, the problem is that you're using the real IMksLibrary instead of a mock, and that's because you obtain a reference to it inside the process method. Here are a few method that you might want to consider:
Change the signature of the process method to receive the reference to the IMksLibrary instance, so that the test code can supply a mock of it
Instead of creating the reference inside the process method inject a reference to the class, either by using some DI framework (e.g. Spring, Guice, CDI, etc.), or as a constructor parameter
Create a protected method called something like getIMjsLibraryInstance() in the class, that will return MksLibFactory.getDefault(), and use it instead of the explicit code (this is the Extract Method refactoring that can be automatically done by most IDEs for Java nowadays). In the test code, you need to create a subclass (this is why it's my least favorite method) which overrides this method and returns a mock, and test the subclass instead of the real class. Notice that this is the ONLY method that you should subclass
You might feel deterred from using the third method, since in effect, you're not really testing the class that you meant to test (but rather a subclass of it). I tend to agree that this has a bed smell to it. However, keep in mind, that unlike the other two methods, this will not require any changes to the clients of the class (this is a pretty strong argument in favor of it).
There are other methods that you can use, but they are pretty similar in nature to the first two methods, and they also require some changes in the code.
If you feel that any "regular" method of testing is not good enough (due to code changes or whatever other reason), you are welcomed to take a look at PowerMock, which will enable you to intercept the static method call that returns the IMksLibrary instance, and return a mock instead. A word of caution though. There are some serious coupling that happens when these type of solutions are used, so it is usually not highly recommended, unless you are really in a dire need.

Related

Mockito: verify arguments passed to new

I'm trying to work out how to verify the parameters passed to a mocked constructor in Mockito. A simplified version of my code is:
class Mocked {
Mocked(String first, String second, int value) {
}
}
class Target {
void testMe() {
new Mocked("Hello", "World", 99);
}
}
#Test
public void test_Target() {
try (
MockedConstruction<Mocked> mockedNew = mockConstruction(Mocked.class);
) {
new Target().testMe();
Mocked mocked = mockedNew.constructed().get(0);
// TODO: verify all arguments passed to mocked
}
}
The class I'm trying to test is "Target"
Target uses an instance of the "Mocked" class. In real code code I'll want to use an actual instance of Mocked, but for the purposes of testing I want to mock it out so I can test "Target" in isolation of "Mocked". I've used the mockConstruction construct to do this.
In my final version of my code the arguments passed to the Mocked constructor are not hardcoded. Instead there will be some business logic to derive them, so and I want to verify they have been derived out correctly. But how?
None of the examples I've Googled show show me how to do this, and org.mockito.Mockito.verify() doesn't appear to have a way to test a constructor.
The only solution I can see is to add mock initialiser function that copies the argument into local variables. But this involves making those variables effectively final (so final one element array) and ugly casts. Surely there has to be something better than that!
What have I missed?
As far as I know, this is not possible using the Mockito API.
You can try a design change where a new MockedFactory class is responsible for creating Mocked objects. You can create a MockMockedFactory for your tests and inject it into Target to use. You will be able to verify the methods called on this factory by the class under test. Not the nicest, adds boilerplate code, but works.
Also, I guess the newly created object is not returned as testing would not be a problem then. It is worth considering if the method you are testing isn't too big doing too many things at once. Maybe some other refactors could help make it more testable.
Or maybe this one: https://groups.google.com/g/mockito/c/WqPlcNrvbOw?pli=1

Equivalent of Answers.RETURNS_DEEP_STUBS for a spy in mockito

I have been unable to find a way to use "Deep Stubs" for stubbing methods on a spy in Mockito. What I'm looking to do is something like this:
#Spy private Person person = //retrieve person
#Test
public void testStubbed() {
doReturn("Neil").when(person).getName().getFirstName();
assertEquals("Neil", person.getName().getFirstName());
}
The code above compiles with no issues, but upon running the test, it fails saying that the return type (the Name class, in this case) cannot be returned by getName().
Normally, when mocking, you have to use
#Mock(answer = Answers.RETURNS_DEEP_STUBS) for each mocked object. However, spy does not seem to have anything like this.
Has anyone ever successfully done deep stubbed mocking using a spy?
The error I'm receiving is listed below:
String cannot be returned by getName()
getName() should return Name
Due to the nature of the syntax above problem might occur because of:
1. Multithreaded testing
//I'm not doing multithreaded testing
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies with doReturn|Throw() family of methods
//As shown above, I'm already using the doReturn family of methods.
While I'd still like to know if there's a better way to do this, I'd like to post a solution for anyone who comes looking.
The solution below works fine, by requiring you to create a new mock (or even a real object/spy) for each level of your dependencies. In other words, instead of chaining your method calls to create your stub, you mock each level individually.
#Spy private Person person = //retrieve person
#Mock private Name name;
#Test
public void testStubbed() {
doReturn(name).when(person).getName();
doReturn("Neil").when(name).getName();
assertEquals("Neil", person.getName().getFirstName());
}
You can get a little closer to the deep stubs you want by using doAnswer(RETURNS_DEEP_STUBS), but you can't override arbitrarily-deep method calls without taking care to stub their parent calls. I'd stick to manual single-level-deep mocks as you do in your answer, or use even less mocking if possible.
A spy's default behavior is to delegate to its real method call, which will typically return a real object (like your Name) and not a Mockito spy. This means that you won't normally be able to change those objects' behavior using Mockito: a spy isn't really the same class as the object being spied on, but rather is a generated subclass where every field value is copied from the spied-on value. (The copying is an important feature, because a delegating spy would have very unintutitive behavior regarding this, including for method calls and field values.)
Foo foo = new Foo();
foo.intValue = 42;
foo.someObject= new SomeObject();
Foo fooSpy = Mockito.spy(foo);
// Now fooSpy.intValue is 42, fooSpy.someObject refers to the exact same
// SomeObject instance, and all of fooSpy's non-final methods are overridden to
// delegate to Mockito's behavior. Importantly, SomeObject is not a spy, and
// Mockito cannot override its behavior!
So this won't work:
doReturn("Neil").when(person).getName().getFirstName();
// Mockito thinks this call ^^^^^^^^^ should return "Neil".
And neither will this:
doReturn("Neil").when(person.getName()).getFirstName();
// The object here ^^^^^^^^^^^^^^^^ won't be a mock, and even if Mockito
// could automatically make it a mock, it's not clear whether that
// should be the same spy instance every time or a new one every time.
In your situation, I'd choose the following, in order from most preferable to least:
Create a real Name object and install it using doReturn. It looks like Name is a data object (aka value object) after all, which likely means it has no dependencies, solid behavior, and difficult-to-mock state transitions. You may not be gaining anything by mocking it.
Create a mock Name and install it as you do in your answer. This is particularly useful if Name is more complicated than it looks to be, or if it doesn't actually exist in the first place.
Replace getName to return a deep stub...
doAnswer(RETURNS_DEEP_STUBS).when(person).getName();
...which you can then override...
doReturn("Neil").when(person.getName()).getFirstName();
...even for arbitrarily deep values.
doReturn("Gaelic").when(person.getName()
.getEtymology()
.getFirstNameEtymology())
.getOrigin();
As a final editorial, one of the hazards of partial mocks is that it makes it really hard to tell which behavior is real and which is faked; this might make it hard for you to guarantee that the behavior you're testing is prod behavior and not mock behavior. Another hazard of deep stubbing is that you may be violating the Law of Demeter by definition. If you find yourself using this kind of technique often in tests, it may be time to consider rearchitecting your system under test.
#Test
public void listTypeTest() throws Exception {
doCallRealMethod().when(listType).setRecordCount(new BigInteger("556756756756"));
listType.setRecordCount(new BigInteger("556756756756"));
doCallRealMethod().when(listType).getRecordCount();
assertEquals(new BigInteger("556756756756"), listType.getRecordCount());
}

How to mock static method with same parameters differently in a test?

This seems highly unlikely, but is there a way I could mock a static method in a certain way and the second time in another way?
A case scenario -
if(StringUtils.isEmpty("")) {
throw Exception();
}
...
if(StringUtils.isEmpty("")) {
doSomething();
}
The test is written in following way.
mockStatic(StringUtils.class);
when(StringUtils.isEmpty("")).thenReturn(false);
/*Is it possible to make this behaviour run only once such that second time
when it is called we can mock it again.*/
limitStaticMock(times(1));//Is this possible?
when(StringUtils.isEmpty("")).thenReturn(true);//Setting behaviour again.
You shouldn't use mocking to control such "internals".
You can easily control what your code under test is doing by controlling the string value that gets to that static call. You want the test to give true; then write a test that pushes in an empty string; and that expects an exception.
You have another production code method that shouldn't throw - then write up another test; and do the necessary setup.
But do not start mocking such methods. If you think you have to, then your design is not testable; in other words: broken! Fix your design, instead of using the big mocking hammer!

How to mock a method call without actually calling its submethods

I started using JUnits (Mockito) from yesterday. I searched for similar question, but didn't find.
I have a class with method method1() which in turn calls method2().
I don't want to mock method2
I am mocking call to method1(). I was expecting that it would return the custom object(without going ahead and calling method2) which I want. But instead it proceeds and tries to call method2().
class A {
method1() {
//do something.
method2();
}
}
I mocked method1 and return any object (say new Integer(1)).
I dont want method2 to be called. but when I am debugging this Junit. It goes and calls method2. Hence fails.
When using syntax like this:
#Test public void yourTest() {
A mockA = Mockito.mock(A.class, Mockito.CALLS_REAL_METHODS);
when(mockA.method1()).thenReturn(Integer.valueOf(1));
}
then the first thing Java will do is to evaluate when(mockA.method1()), which requires calling mockA.method1() to get a value to pass into when. You don't notice this with other mocks, because Mockito mocks return nice default values, but with spies and CALLS_REAL_METHODS mocks this is a much bigger problem. Clearly, this syntax won't work.
Instead, use the methods beginning with do:
#Test public void yourTest() {
A mockA = Mockito.mock(A.class, Mockito.CALLS_REAL_METHODS);
doReturn(Integer.valueOf(1)).when(mockA).method1();
}
As part of .when(mockA), Mockito will instead return an instance that has no behavior, so the call to method1() never happens on a real instance. do syntax also works with void methods, which makes it more flexible than when(...).thenReturn(...) syntax. Some developers advocate for using doReturn all the time; I prefer thenReturn because it's slightly easier to read, and can also do return type checking for you.
As a side note, prefer Integer.valueOf(1) over new Integer(1) unless you absolutely need a brand new instance. Java keeps a cache of small integers, and this can be faster than allocating a brand new reference if you need to manually box an int into an Integer.
Usually you mock interfaces or abstract classes and provide implementations of abstract methods. In your case you want to substitute the real implementation of a concrete class. This can be achieved via partial mocks.
http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#16

How to override instance/concrete class's method runtime? (e.g. reflection, cglib)

What I wanna do is a method that can
generate instance of Class X (a class variable passed in arg) and
override some of it's method
More specifically, the parent class X I want to override contains
Contains no default constructor (e.g. all constructors with args)
Constructors calling non-private method within the same class
Originally I thought it's quite simple to use reflection or something similar,
Then I found there's limitation on implementing my requirement.
For refection: Can only override "interface" via java.lang.reflect.Proxy
http://download.oracle.com/javase/1.3/docs/guide/reflection/proxy.html
for cglib: it cannot create instance of no default constructor and constructor calling non-private member methods
http://insufficientinformation.blogspot.com/2007/12/spring-dynamic-proxies-vs-cglib-proxies.html
I think this is achievable, since Mockito can do all kinds of method injection runtime.
Please anyone give some advise, Thanks.
The pseudo-code I image is like this:
createAndOverride(Class X) {
X newObj = X.newInstance(args) {
#override
methodOfX(args2) {
...
}
}
return newObj;
}
Original problem scenario
I was intended to test a Class which has several methods calling X1.get(), X2.get(), X3.get()
In some test case, I need to make Xn.get() to return something I can control for test (e.g. null)
Due to below constraint:
But due to mock tool restriction to JMock 1.0 (I have no control :( ), so I cannot just simply mock Xn.get() to returns "someSpecifiedObjects"
Xn has no null constructors and constructors calling non-private member
My workaround is self made Xn Class and pass them to test case to let Cn.get() to be expected
code example:
ClassToTest.SomeMethod(new X1() {
#override
get() {
return someSpecifiedObjects;
}
});
And this kind of thing is spread-ed over the Test Case.
Therefore, In order to reduce duplicate code, I would like to build a method to generate Xn instance with specified overrided method for test. e.g.
X1 x1 = createAndOverride(X1);
Then, the problem of this post comes
are you looking for something like javassist? You can instrument code and inject your methods at runtime. I personally try to avoid byte code manipulation as much as possible. Can you not have these overrides in your code base rather than doing on the fly? May be something like wrappers?
So what I think you need is a similar functionality to C#'s Reflection.Emit:
Using Reflection.Emit to create a class implementing an interface
Java Equivalent of Reflection.Emit
Dynamically Create Java Classes With JavaClassCreator
While I haven't done this myself, I think you should be able to use reflection/emission and dynamic type creation in order to achieve what you're looking for. However, I would still like to mention that if you're trying to test "functionality" that's not int he code path of the function you're testing, then you probably shouldn't be testing it at all. For example:
SomeObjectInterface get()
{
if(_someObjectStateIsSet)
{
// Return a concrete implementation A
return new ConcreteImplA();
}
else
{
// Return a concrete implementation B
return new ConcreteImplB();
}
}
In this case get has no code path that would return null, so you shouldn't need to test for null. I'm not sure if I understood your question 100% correctly, especially why you're testing for null, but consider the above advice and see what works for you.

Categories