Can JMockit initiate mock objects with argument constructor? - java

When I put the #Mocked annotation on a object which has only constructor with parameters, will this object be initiated rightly?

When I put the #Mocked annotation on a object which has only constructor with parameters, will this object be initiated rightly?
No.
A mock will be created that has the same interface. That means it will have the same public methods and if the test class is in the same package it will also have the same protected and package private methods accessible.
This mock will not invoke the real methods of the mocked class (unless you configure it so).
This means that for every method that is expected to be called by your code under test (cut) and that has a return value defined you have to configure your mock so that is returns a value your cut shall work with in that particular test.
This configurable return values and the verify capabilities of the mocks are the reason why we use mocking frameworks.
Attention
If you want to mock the call to a method which accesses a member initialized by the mocked classes constructor you have to use the form
doReturn(SOME_VALUE).when(mock).methodToBeCalledByYourCut();
because the form
when(mock.methodToBeCalledByYourCut()).thenReturn(SOME_VALUE);
will raise a NullPointerException in that special case.

Related

How do I manipulate an argument with mockito

I am using junit to run a few unit tests. One of these calls a method in an object that I mock using mockito like;
#Mock
private MyClass myClass;
I then set up mockito to do something like
Mockito.when(myClass.foo(Mockito.any()).thenReturn(bar);
Now myClass.foo actually takes another one of my classes (say class Person) as an argument and what I would like to do is something like this
Mockito.when(myClass.foo(Person parson)).thenDo(person.setName("Name")).thenReturn(bar);
That is of course pseudo code but I hope it illustrates what I am trying to do. Is this possible?
You need to use thenAnswer or its twin doAnswer method.
See Mockito : doAnswer Vs thenReturn
You should use thenReturn or doReturn when you know the return value at the time you mock a method call. This defined value is returned when you invoke the mocked method.
Answer is used when you need to do additional actions when a mocked method is invoked, e.g. when you need to compute the return value based on the parameters of this method call.
If your answers become too complicated, consider using a fake instead of a mock.
In this case if your goal is to set field of Person object you can do that before or after the line:
Mockito.when(myClass.foo(Mockito.any()).thenReturn(bar);
doAnswer() would help do operations based on input, but operations would be performed on copy of arguments not the original arguments.

Mockito: When is #Mock object get initialized and which constructor it calls

I'm trying to figure out how mockito is working behind in order to debug. I was wondering for the object with #Mock annotation, when is it initialized? Like, before #Before or after #Before?
And if there're several different constructors, how is mockito determines which constructors to call?
And if I use jmockit #Mocked instead, are there any different answers of the questions above?
Thank you!
Mock objects created with Mockito don't call any constructor or static initializer. (This is achieved through Objenesis in older versions of Mockito, and ByteBuddy in newer versions.) Consequently, all of the fields are uninitialized, and no side effects in constructors happen at all including any exceptions you might see thrown.
In contrast, spy objects do have their constructors called. Mockito will default to calling a no-argument constructor (public or private) if you don't initialize the field, and you can call the constructor of your choice inside the initializer.
The order of #Mock annotation initialization depends on which technique you use to initialize mocks:
If you use MockitoJUnitRunner, mocks are initialized after initializer blocks, constructors, and #Rules, and before any other #Befores as defined in BlockJUnit4ClassRunner.
If you use MockitoRule, mocks are initialized before any #Before methods, but in undefined order compared to other #Rules unless you chain them manually with RuleChain.
If you use MockitoAnnotations.initMocks(), mocks are initialized exactly when you call that method, which is after initializer blocks and rules, and (if you call within a #Before method) in undefined order compared to other #Before methods.
#Mocked fields are initialized right after the test class is instantiated by the test runner (JUnit, TestNG), before any #Before/#BeforeMethod-annotated methods get executed.
The mocked instance is created by JMockit without calling any constructor in the mocked class.
The above answers also apply to Mockito (and any other mocking library with similar features).

Mockito can't set up when as throws exception in method

This seems like it should be simple but I'm running around in circles.
I have:
#Mock
SimpleAbstractCacheWithInputs<Key, Value, Inputs> underlyingCache;
I then try to set up a call on the cache in setup():
when(underlyingCache.getOrCreate(usdgbpKey)).thenReturn(usdgbpCfi);
But this throws a null pointer exception from within getOrCreate() because it's trying to execute the actual code in the real object, not mocked at all, and that isn't set up.
But I don't want to ever run getOrCreate real code, I just want it to return the mocked value!
So how do I do this without having to set up everything inside underlyingCache that I'm never going to use in order to mock this one method call?
If you were concerned about the behavior of a spy or already-stubbed object, I would recommend this syntax, which doesn't rely on calling the mocked object:
doReturn(usdgbpCfi).when(underlyingCache).getOrCreate(usdgbpKey);
...but that all seems right. If you're using the #Mock annotation, then the entire object should be mocked, or null if you've forgotten a Mockito runner/rule/initialization.
There are a few cases where mocking would fail and you get the actual behavior instead:
If the method is final, because then Mockito can't override the method (through a proxy).
If the class is final, because then Mockito can't override the class (through a proxy).
If the class has complicated access semantics, such as a public nested class that accesses private parent methods, because the Java compiler may rewrite the method call through a synthetic method that Mockito can't (easily) mock.

Configuring state of mocked object for different scenarios

I've a DAO and a service class. In the service class CapService, I've #Autowired a reference of DAO class CapDAO. The CapDAO class has a private instance field of type int, that has it's value injected from a properties file using #Value annotation.
class CapDAO {
#Value("${someProperty}")
private int expiryTime;
}
class CapService {
#Autowired
private CapDAO capDAO;
}
There is a method - retrieveCap() in the CapDAO class, which retrieves the caps from the database, based on the expiryTime. That method is invoked from another method in CapService class.
The CapService class uses the list returned from DAO method to create another object wrapping that list. And finally it returns that data structure.
Now, I'm testing a scenario using Mockito framework. I've two scenarios. In both of them, I want to invoke method of CapService class, which will get me the object. The list retrieved form database, will depend upon the value of expiryTime in the CapDAO class. And so will the content of the object returned by CapService class method.
In test, I'm invoking the method in Service class, and checking the value returned. Since DAO is reading expiryTime from properties file, both the test scenarios cannot pass with the same configured value. I've to have two differently configured DAO instance to be injected into Service class.
So, my question is - is there any way I can configure the expiryTime in CapDAO class, to create two different instance, or may be in a single instance only, and inject those in CapService based on scenario? No I don't have any setter for expiryTime. Yes, I knwo I can use reflection, but I would like to keep that as my last resort.
Short answer
reflection is easiest possibility, you can simply use ReflectionTestUtil. Note: If you have an interface which CapDAO implements, you need also AopUtils
Long answer
If you don't wanna use reflection, you need separate your context and test to get this work:
// context1.xml
<context:property-placeholder location="classpath:test1.properties"/>
// context2.xml
<context:property-placeholder location="classpath:test2.properties"/>
Then you can define someProperty with some other value in the properties.
personally i will recommend reflection.

How to write a junit testcase for a void method that creates a new object

public class SupportController{
public void disableUserAccount(String username) throws Exception {
UserAccount userAccount =
new UserAccount(Constants.SYSTEM, Constants.CONTAINER, username);
UserAccount.disableAccount();
}
}
How would i test that the useraccount created is disabled?
I would suggest using Mock Objects.
Besides that, you can check the JUnit FAQ, where you can find a section about testing methods that return void.
Often if a method doesn't return a value, it will have some side
effect. Actually, if it doesn't return a value AND doesn't have a side
effect, it isn't doing anything.
There may be a way to verify that the side effect actually occurred as
expected
There are three basic solutions:
Use a factory class that can be mocked
Use PowerMock which can mock calls to constructors
Update the class to use a default scope or protected scope factory method which could be overridden in a test env.
PowerMock does not always play well with other runners (for example SpringJUnit4TestRunner). I usually avoid it for this reason and the fact that it modifies the compiled code.
The overridable factory method is another option. To do this you must extend the class and override the factory method. This means that the test is running against an instance of the class under test that is not actually the class under test but a testable subclass. This has test-smell to me so I tend to avoid it where possible.
The factory class method is my preferred solution. Pass in a Factory class that be default creates the UserAccount. In your test provide a mocked (I use Mockito) version of the factory.

Categories