I have method getAllCustomers inside CustomerService class. Inside this method I call another static method from CustomerDao class.
Now when I am writing the junit for method getAllCustomers inside customerService class, where I want to mock the call to
static method of CustomerDao i.e. getAllCustomers. Here is the brief code snippet of method getAllCustomers inside
CustomerService class. Is it possible to mock the static method call using unitils?
Public static List<CustomerDate> getAllCustomers()
{
//some operations
List<CustomerDate> customers=CustomerDao.getAllCustomers();// static method inside CustomerDao
//some operations
}
Above code is just an example I am trying to put. Please avoid the discussion why these methods are designed as static
methods. That's a separate story .)
I doubt whether it can be achieved with unitils.
But please consider using PowerMock instead which seems to be capable of handling what you need. It can mock static methods,private methods and more (Ref: PowerMock)
This would be a matter of:
Setting up the mock
Calling the mock and expecting some data back
Verifying the end result of your call given your data
So, without really much ado about the static call, here's the way you can set it up in PowerMock:
#RunWith(PowerMockRunner.class)
#PrepareForTest(CustomerDao.class)
public class CustomerTest {
#Test
public void testCustomerDao() {
PowerMock.mockStatic(CustomerDao.class);
List<CustomerDate> expected = new ArrayList<CustomerDate>();
// place a given data value into your list to be asserted on later
expect(CustomerDao.getAllCustomers()).andReturn(expected);
replay(CustomerDao.class);
// call your method from here
verify(CustomerDao.class);
// assert expected results here
}
}
Related
I meet a question about the mock private method in a injected mock annotated class. My code is like following
public class foo {
#Autowired
fooBean fooBean;
public void method1() {
this.method2();
}
private void method2() {
fooBean.someMethod();
system.out.println("Hello world");
}
}
when I create a UT class with powermockito, the foo class should be #injectMocks, since the fooBean should be injected as mock class. But when foo class is marked as #injectMocks, it can't be mock its private method using like "doReturn("xxx").when(foo,"method2")", it will raise error about this can not be applied to injectMocks.
It is blocked. Don't know how to continue.
TLDR; you cannot use InjectMocks to mock a private method.
You should mock out implementation details and focus on the expected behaviour of the application. It is important as well that the private methods are not doing core testing logic in your java project.
Focus on writing functions such that the testing is not hindered by the private method. If it is not possible, it is worth asking what is the private method doing that is so valuable to your function and why it has to be private.
There are other ways to test private methods - You could use the Reflections java library, this would let you stop methods at runtime and inject specific values into them. But, again, this is finding a solution to a problem that does not need to exist.
I am using JDK 11 and spring boot.
I am implementing a rest API and have 3 layers:
controller
service layer
data access layer
I had classes against interfaces at the data-access-layer and did not have any interface at the service layer.
I wrote integration tests using MockMvc, Mockito, etc to exercise the whole path for each point, exposed by the controller. This was not a problem until I tried to introduce the interface at the service layer.
Initially, I mocked only repositories/Daos. So the class structure looked like:
public interface ClientRepo{
......
}
public class ClientRepoImpl implements ClientRepo{
......
}
Mocked the returned data as:
#MockBean
private ClientRepo client;
....
Mockito.when(client.isExistFkUnitId(Mockito.any(UUID.class))).thenReturn(false);
Everything was fine so far.
Now I have introduced interface at the service layer as :
public interface ClientService{
......
}
public class ClientServiceImpl implements ClientService{
......
}
And tried ( Trying to call actual service method):
#MockBean
private ClientService clientService;
....
Mockito.when(clientService.isExistFkUnitId(Mockito.any())).thenCallRealMethod();
But getting nothing but null all the time.
Is there a way to make the real method call keeping the interface?
I think you want to use #Spy annotation instead of #Mock annotation on the field where you want to call the real method. I don't happen to have an example to verify this though.
https://javadoc.io/doc/org.mockito/mockito-core/2.21.0/org/mockito/Spy.html
Then you can do doCallRealMethod().when(clientService.isExistFkUnitId(Mockito.any())).
Because with a spy object you call doReturn/when instead of when/doReturn.
https://javadoc.io/doc/org.mockito/mockito-core/2.21.0/org/mockito/Mockito.html#do_family_methods_stubs
Well, there is no "real" method to call. (Ignoring the fact that default methods in interfaces are a thing nowadays)
Generally, unit tests should be written for the target class in an isolated fashion. Like this, you are always "testing" the "isExistFkUnitId" method as well.
You could set the mock up for specific values:
Mockito.when(clientService.isExistFkUnitId("valueA").thenReturn("answerA");
Mockito.when(clientService.isExistFkUnitId("valueB").thenReturn("answerB");
Anyways... to respond to your actual question:
If possible, you can instantiate the implementation in a way that the desired method is working and call it through the mock:
ClientServiceImpl clientServiceImpl = new ClientServiceImpl(...);
// spaghetti code only for demonstration purposes ;)
Mockito.when(clientService.isExistFkUnitId(Mockito.any())).then(i -> clientServiceImpl.isExistFkUnitId((String) i.getArguments()[0]));
POC test:
#Test
public void testit() {
Myclass myclass = new Myclass();
Myinterface mock = Mockito.mock(Myinterface.class);
Mockito.when(mock.myMethod(Mockito.any())).then(i -> myclass.myMethod((String) i.getArguments()[0]));
assertThat(mock.myMethod(" works")).isEqualTo("yeehaa works");
}
public interface Myinterface {
String myMethod(String params);
}
public static class Myclass implements Myinterface {
#Override
public String myMethod(String params) {
return "yeehaa" + params;
}
}
Not exactly a beautiful solution, but if there is no way around it, it should work.
As you are mocking an interface Mockito doesn't know which implementation are you referring. The only way will be to use the Class.
I was having the same problem. My problem was due to the ClientService having dependencies that were not mocked when I set up the tests in this format. So ClientService had a mock, but if I tried clientService.productService.get() or something of that nature the dependant productService was always null. I solved this using testing reflection:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps!
I have a class that implements a cache and I want to write a JUnit test for it.
The class implements and interface with methods like:
public void insert(Object key, Object value);
public Object getFromCache(Object key);
and the basic implementation is a singleton.
I am writing a JUnit test but I don't know how to properly create a dummy cache with data in order to use for testing.
Right now I am doing:
#Test
public void myTest() {
MyCache cache = MyCache.getInstance();
populateWithData(cache);
//test cache
asserEquals etc
}
How can I avoid using the getInstance() and not populate on each test?
Apparently I slightly misread your question.
As the other two answers state, if you want to have a specific cache which you can read from when running each testcase, you could use a ´#before´ method, which initializes your object to be used in your testcase. Each ´#before´ method defined is called prior to calling each testcase. This means that you can write the code to instantiate the object once instead of many times.
Note that if you want to do something different in a testcase, consider adding the customization at the top of that, instead of edition your #before method, since that will impact all your testcases.
Just for clarity's sake, I will include some code:
MyCache cache = null;
#before
public void initCache(){
cache = MyCache.getInstance();
populateWithData(cache);
}
// ... rest of your program here ...
Original answer:
You can use this if you want to do more fancy testing of more complicated objects. This can still be used in conjunction with the ´#before´ annotation
You could try mockito...
This is basically a framework to mock off a function or class, that you are not interested in implementing in its totally, especially for testing.
Here is a sample using a mocked off list:
import static org.mockito.Mockito.*;
// mock creation
List mockedList = mock(List.class);
// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();
// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();
// you can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
// the following prints "first"
System.out.println(mockedList.get(0));
// the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));
You can basically tell mockito which functions you expect to call on the object, and what you expect the result to be... very versatile. I expect that it will fulfill your needs.
'Reset' singleton before each test. More details can be found here.
For example:
#Before
public void resetMyCacheSingleton() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field instance = MyCache.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(null, null);
}
You can use #BeforeClass annotation to do something which will be common and may be computational expensive stuff.
This will ran only once before all the testcases.
#BeforeClass
public static void myTest() {
MyCache cache = MyCache.getInstance();
populateWithData(cache);
//test cache
asserEquals etc
}
P.S. Since #BeforeClass can be used with static method only, populateWithData() needs to be static as well. and since populateWithData() method is static, variables used inside it must be static as well.
You can also check #AfterClass to clean/reset some data/resources.
Let's suppose I have a test class A which extends from class B. This class A has one method with #BeforeClass annotation:
#BeforeClass
public static void setUp(){
createFakeData();
}
The method createFakeData() is in class B and its function is to create an object in database.
In order to do that, I have a bean in class B:
#Autowired
private DummyObjectsFactory dummyObjectsFactory;
And the content of the method createFakeData() could be something like that which returns a FakeData object:
public FakeData createFakeData() throws Exception
{
return dummyObjectsFactory.createFakeData();
}
The problem I'm facing is that the #BeforeClass method has to be static, that means that the createFakeData method has to be static too. But I cannot set that method to static because my bean dummyObjectsFactory will be always null.
How can I make my createFakeData method static avoiding my dummyObjectsFactory bean to be not null?
As far as I know, that is not permitted in JUnit. However you can do some things for arrange it.
First, you can use TestNG, which allows to do exactly what you want.
If that is not an option, instead of using #BefloreClass annotation, you can use #Before. The difference between both is that #BeforeClass executes the method before all the tests while #Before executes the method before each test. If you use #Before, I would annotate the class with #Transactional in order to delete the data saved in the database.
In the end, if you don't want to execute the method for each test, you can use #Before and flat the call:
#Before
public void init(){
if(!fakeDataCalled){
createFakeData();
fakeDataCalled=true;
}
}
I believe you want to annotate your test class (B) with #RunWith(SpringRunner.class) so that the autowiring happens correctly.
Take a look at section 15.4.4 in the Spring Reference.
You can also just browse to that page and search for "RunWith"
Caveats:
I don't like static methods. They tend to make unit testing difficult.
I don't like extending tests to make other tests. I find it easier to make each test standalone and use composition for any shared functionality (i.e. make utility classes for shared test functionality that reside in the test source tree).
I don't like my unit tests depending on autowiring. I mock all the dependencies and inject them with either reflection or the #InjectMocks annotation.
So, basically, a there is some poor code that I cannot change that needs to be tested. Traditionally, you inject your mocked dependencies, but with this code, I cannot do so, because there are no setter methods. Worse, the function I need to test calls a bunch of static factory methods-I can't just use the MockUp strategy to swap out the implementation there, because there is no class instance to be injected at all.
In C/++, you can retrieve a pointer to a function and know it's type by it's signature. If you changed the pointer, then you could potentially change how the stack was constructed by the compiler and you could pass function's around and all that Jazz.
Is there a way to use the Deencapsulation API to replace a static method implementation? Using this, I could write my own class, descend from the traditional, but return mocked objects in order that dependency injection still be achieved?
public class TestedClass {
public static void testedMethod() {
UnMockableType instanceVariable =
UnInjectableFactory.staticFactoryConstructor();
instanceVariable.preventControlFlowInfluenceThroughMocking();
}
}
Easy enough:
#Test
public void exampleTestUsingAMockUp()
{
new MockUp<UnMockableType>() {
#Mock
void preventControlFlowInfluenceThroughMocking() {}
};
TestedClass.testedMethod();
}
Above, UnInjectableFactory isn't mocked because it doesn't need to be (assuming it simply instantiates/recovers an UnMockableType).
It could also be done with #Mocked and the Expectations API.