Unit testing a fluent interface with Mockito - java

I want to mock the DAO interface used in the builder pattern as shown below. However when I run the test below it passes indicating that my mock object is never called. What am I doing wrong?
public class DBContent {
...
public static class Builder {
DAO dao = new DAO();
...
public Builder callInsert() {
...
long latest = dao.insert();
...
}
}
...
}
#RunWith(MockitoJUnitRunner.class)
public class DBContentTest {
#Mock
DAO dao;
#Test
public void test() {
when(dao.insert()).thenReturn(1111L);
DBContent db = DBContent.db()
.callInsert()
.callInsert()
.callInsert()
.build();
verifyZeroInteractions(dao);
}
}

Use PowerMockito instead. There you can define that whenever you have a call to a constructor of DAO, return my mocked object instead of returning actual DAO object.
Please refer this to learn how to use PowerMockito.

Related

Mockito Spying on Class that has an internal method reference

I'm seeing a different in behaviour when spying on a service using the #Spy annotation and having Mockito create the Server verses explicitly calling the constructor.
public class MyService {
private final Supplier<String> methodBCall;
public MyService() {
methodBCall = this::methodB;
}
public void methodA() {
methodBCall.get();
}
public String methodB() {
return "methodB";
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyTest {
#Spy
private MyService myService1;
#Spy
private MyService myService2 = new MyService();
#Test
public void testSucceeds() {
myService1.methodA();
verify(myService1, times(1)).methodA();
verify(myService1, times(1)).methodB();
}
#Test
public void testFails() {
myService2.methodA();
verify(myService2, times(1)).methodA();
verify(myService2, times(1)).methodB();
}
}
The failing test fails with
Wanted but not invoked:
myService2.methodB();
-> at com.phemi.services.policy.impl.MyTest.testFails
Why do these two behave differently? What is Mockito doing to initialize myService1 that enables it to spy on methodB?
This is a simplified example, in my case to test my service properly I need to call its constructor with an argument (and so cannot use the #Spy with a default constructor). However, when I do that I cannot properly verify method calls.
The spy on myService2 is only created after the object has been constructed, so having a method call in the constructor is not helpfull as it contains a method reference to the initial object (which is not the spy object).
The difference becomes more evident when you compare the implementation for both cases:
Mockito.spy(Class)
public static <T> T spy(Class<T> classToSpy) {
return MOCKITO_CORE.mock(classToSpy, withSettings()
.useConstructor()
.defaultAnswer(CALLS_REAL_METHODS));
}
Mockito.spy(Object)
public static <T> T spy(T object) {
return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
.spiedInstance(object)
.defaultAnswer(CALLS_REAL_METHODS));
}
As you can see the first case, based on a class (which is used if no instance for #Spy was created), creates a mock first and uses the constructor on the mocked object.
In the second case the constructor is not considered instead a different instance is created.

How to mock a method call within a method for which i am writing junit test

Could someone help me with mocking a method call within a method
my code is like :
public class Service {
public List<Bean> Filter(Bean bean){
List<Bean> Filtered_List = getUtilityService.getBeanList();
//Do something
return beanList;
}
}
Now i want to write test case for Service class . How can i mock :
List Filtered_List = getUtilityService.getBeanList(); and set values in it.
The clean solution is to extract UtilityService to a field and pass a mock to the constructor.
public class Service {
private UtilityService utilityService;
public Service(UtilityService utilityService) {
this.utilityService = utilityService;
}
public List<Bean> Filter(Bean bean){
List<Bean> filteredList = utilityService.getBeanList();
//Do something
return beanList;
}
}
You can also introduce a UtilityServiceFactory and have a utilityServiceFactory field in the Service.
public class Service {
private UtilityServiceFactory utilityServiceFactory;
public Service(UtilityServiceFactory utilityService) {
this.utilityServiceFactory = utilityServiceFactory;
}
public List<Bean> Filter(Bean bean){
List<Bean> filteredList = utilityService.create().getBeanList();
//Do something
return beanList;
}
}
If getUtilityService is located in Service class, there is also a dirty solution: partial mock. But I do not recommend it. It's better to refactor your code and use one of previous approaches.
EDIT:
Constructor injection with #InjectMocks is not the best idea but here you are:
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
//other imports
#RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
#Mock
UtilityService utilityService;
#InjectMocks
Service service = new Service(null);
#Test
public void shouldFilterBeans() throws Exception {
//given
given(utilityService.getBeanList()).willReturn(asList(new Bean()));
//when
List<Bean> result = service.filter(new Bean());
//then
assertThat(result).hasSize(1); //probably you want to check something else
}
}
to test a method including its own parameter and return value, like the Filter method in your code, it's enough to just pass a Bean instance to it, and then assert the returned List<Bean> object equals to your expected result. generally, for this kind of method, i think it's no need to use mock frameworks.
but if you really want to test the getUtilityService().getBeanList() method call, you should refactor your code:
addfield UnitilityService service and its corresponding setter method in your class Service
in your unit test code, inject a mocked service using the setter method to the object under test and given a returning value for its getBeanList() method, then invoke your Filter method, finally, verify the method call. for the detailed implementation, you can refer the answer of #woru.

How to mock a method call inside another method

Here is my code:
`public class Service {
callSomeService(ContextTpye1 c1,Parameter p){
//do something here
ContextTpye2 c2 = constructContext(c1,p);
if(c2.timeout()){
c2.audit();
}
}
}`
In the unit test, the Service, Parameter and ContextTpye1 are initialized. Is it possible to only mock c2.audit()? I wanna it to doNothing here. Thanks.
So the way I would attack the problem assuming constructContext(c1,p) is public is to when testing the Service class is to spy on the Service allowing you to mock the constructContext(c1,p) and returning a mock of ContextType2.
public class ServiceTest
{
private Service service = Mockito.spy(new Service());
private ContextType2 c2 = Mockito.mock(ContextType2.class);
#Test
public void testCallSomeService()
{
Mockito.when(service.constructContext(Mockito.eq(ContextType1.class), Mockito.eq(Parameter.class))).thenReturn(c2);
Mockito.when(c2.timeout()).thenReturn(true);
Mockito.when(c2.audit()).doNothing();
service.callSomeService(new ContextType1(), new Parameter());
}
}

Is there anything similar to Junit Setup Method in Mockito

I have the following scenario
interface DAO
{
String a();
String b();
String c();
}
I create a mock of this DAO interface and I feed it to something called DAOProcess. Inside DAOProcess, I have various methods calling DAO methods a, b and c.
Now each time I need to unit test a method in DAOProcess, I'll end up writing when(mockDAO.a()).thenReturn("test").
Is there anyway I can move these when(mockDAO.a()).thenReturn("test") common to all the test cases ?
If your test cases are all in one class you could make use of a method annotated with #Before, e.g.:
...
private DAO mockDAO;
#Before
public void setUp() {
mockDAO = mock(DAO.class);
when(mockDAO.a()).thenReturn("test");
...etc...
}
...
Or, if you need the behaviour over many test classes you could write a utility class to set behaviour on a Mock instance, e.g.:
public class MockDAOPrototype {
public DAO getMockWithDefaultBehaviour() {
final DAO mockDAO = mock(DAO.class);
when(mockDAO.a()).thenReturn("test");
...etc...
return mockDAO;
}
}
And then call MockDAOPrototype.getMockWithDefaultBehaviour() in your setUp method.
You can create an AbstractTestCase class that is abstract and is extended by all test cases where you need this mock. In that abstract test case, you will have the following statements.
#Ignore // just in case your runner thinks this is a JUnit test.
public abstract class AbstractTestCase
{
#Mock
private DAO mockDAO;
#Before
private void setupMocks()
{
when(mockDAO.a()).thenReturn("test")
....
}
}
In your concrete test case classes, you would
public class MyConcreteTestCase extends AbstractTestCase
{
#InjectMocks
#Autowired
private DAOProcess daoProcess;
....
}

JUnit mocking with Mockito, EasyMock, etc

I'm trying to mock a method of an object inside the class I'm testing.
For instance
class ClassToTest {
public doSomething () {
SomeObject a = new SomeObject ();
a.doSomethingElse ();
}
}
Is there a way to mock the methods of the variable "a"? I'd like doSomethingElse to do nothing during testing. I'm currently using Mockito but I'm open to any mocking framework.
Thanks
Yes, there is a way, as shown by the following JMockit test:
public void testDoSomething(final SomeObject mock)
{
new ClassToTest().doSomething();
new Verifications() {{ mock.doSomethingElse(); }};
}
No need to refactor code under test to use a wrapper, DI, etc; simply mock whatever you need to be mocked.
It's not possible to mock the reference "a" when it's declared as a local variable, as in your case. You could consider injecting the dependency to SomeObject, e.g. as a parameter of doSomething method. That way, you can inject a mock of SomeObject in your test instead.
One of the benefits of dependency injection is increased testability.
With some refactoring it is possible, of course:
class SomeObject {
public void doSomethingElse()
{
}
}
class ClassToTest
{
private final SomeObject someObject;
public void doSomething()
{
someObject.doSomethingElse();
}
public ClassToTest(SomeObject someObject)
{
this.someObject = someObject;
}
}
class Test {
#Test
public void testDoSomething()
{
SomeObject someObject = Mockito.mock(SomeObject.class);
new ClassToTest(someObject).doSomething();
Mockito.verify(someObject, Mockito.atLeastOnce()).doSomethingElse();
}
}
I believe you can use EasyMock Class Extensions for EasyMock 2.5 or earlier, and apparently it is included in 3.0. See this part of the previous page for information on what you are trying to do. That said, I haven't personally tried to do that, so I don't know how well it will work.
If you want a new instance in each call, I'd suggest refactoring in the following way:
class ClassToTest {
public doSomething () {
SomeObject a = getInstance();
a.doSomethingElse ();
}
protected SomeObject getInstance() {
return new SomeObject();
}
}
Then you can create a testclass extending ClassToTest, overriding the getInstance() method, with one supplying a mock object.
This is of course only viable if you are ok with exposing the getInstance() method, so I don't recommend it if the class is part of a public API. If this is the case, consider supplying a factory class using dependency injection.
class ClassToTest {
private SomethingElseInterface somethingElseDoer ;
public ClassToTest(SomethingElseInterface somethingElseDoer) {
this.somethingElseDoer = somethingElseDoer;
}
public doSomething () {
somethingElseDoer.doSomethingElse();
}
}
And where you use it:
SomethingElseInterface somethingElseDoer = ...; // in a test, this is where you mock it
ClassToTest foo = new ClassToTest(somethingElseDoer); // inject through constructor
foo.doSomething();

Categories

Resources