Why is my stubbed method returning null? - java

I have a class Dummy. I inject 3 variables. However, one of them is not injectable because it is an interface. So I inject an object, one of whose methods return the needed type.
Class Dummy
{
private final Class1 class1;
private final Class2 class2
private final Interface1 interface1;
#Inject
Dummy(Class1 class1, Class2 class2, HelperClass helperclass)
{
this.class1 = class1;
this.class2 = class2;
this.interface1 = helperclass.somefunction();
}
}
The HelperClass's somefunction returns an instance of Interface1.
This is my test:
#RunWith(MockitoJUnitRunner.class)
Class DummyTest
{
#Mock
private Class1 class1;
#Mock
private Class2 class2;
#Mock
private HelperClass helperclass;
#InjectMocks
private Dummy dummy;
#Before
public void start()
{
Interface1 mockInterface = mock(Interface1.class);
when(helperclass.somefunction()).thenReturn(mockInterface);
}
#Test
public void test()
{
// etc...
}
}
However, interface1 is null when I run the test. What am I doing wrong?

#InjectMocks happens before the #Before annotation.
For this reason (and other reasons), I recommend not using #InjectMocks at all; just build your SUT class in the #Before method with a real constructor.
This ordering is obvious when you add a few print statements to your test class. I removed all the Class1 and Class2 stuff as it's not relevant. See this code run:
#RunWith(MockitoJUnitRunner.class)
public class DummyTest {
#Mock
private HelperClass helperclass;
#InjectMocks
private Dummy dummy;
#Before
public void start()
{
System.out.println("In #Before!");
Interface1 mockInterface = mock(Interface1.class);
when(helperclass.somefunction()).thenReturn(mockInterface);
}
#Test
public void test()
{
System.out.println("In #Test!");
}
public static class Dummy {
public final Interface1 interface1;
public final HelperClass helperclass;
#Inject
Dummy(HelperClass helperclass)
{
System.out.println("In dummy constructor!");
this.interface1 = helperclass.somefunction();
this.helperclass = helperclass;
}
}
private static class HelperClass {
Interface1 somefunction() {
return new Interface1() {};
}
}
private static interface Interface1 {
}
}
Output:
In dummy constructor!
In #Before!
In #Test!
If you insist on doing it with #Mock and #InjectMocks, you could try using the answer argument instead:
#Mock(answer=Answers.RETURNS_MOCKS)
will make helperclass.somemethod() return a mock instead of null.
Honestly, it's not surprising that it works this way. The authors of Mockito really don't like Partial Mocks / Stubs, and explicitly say so in their documentation:
As usual you are going to read the partial mock warning: Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects. How does partial mock fit into this paradigm? Well, it just doesn't... Partial mock usually means that the complexity has been moved to a different method on the same object. In most cases, this is not the way you want to design your application.
However, there are rare cases when partial mocks come handy: dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.) However, I wouldn't use partial mocks for new, test-driven & well-designed code.
Having helperclass return something other than null is a partial mock, and therefore they won't like it.

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.

PowerMock static method mocking isn't taken into account for each #InjectMocks invocation

I want to write some unit tests, that use JUnit 4.12, Mockito 1.9.5 and PowerMock 1.6.1.
The class has some fields annotated with #Mock, as well as some fields annotated with #InjectMocks.
The attribute that is annotated with #InjectMocks reaches at some point a parent constructor which contains some static method invokation, that should be mocked with PowerMock.
The problem is the first test works seamlessly, while the second test does not seem to mock the static methods at all.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ StaticClass.class })
public class TestClass {
#Mock
private SomeClass attribute1;
#InjectMocks
private SomeOtherClass attribute2;
#BeforeClass
public static void setUp() {
PowerMockito.mockStatic(StaticClass.class);
when(StaticClass.staticMethod(any(), any()).thenReturn(new SomeConcreteClass());
}
#Test
public void test1() {
assertEquals(attribute2.method1(), value1);
}
#Test
public void test2() {
assertEquals(attribute2.method2(), value2);
}
}
public class SomeOtherClass {
private SomeClass attribute;
public SomeOtherClass() {
SomeConcreteClass value = StaticClass.staticMethod(argument1, argument2);
value.someOtherMethod();
}
}
As mentioned before, the first test passes and the StaticClass.staticMethod() is mocked as expected by PowerMock.
The second test does not pass and it throws a NullPointerException at line when someOtherMethod is called on value (because value = null, as the StaticClass.staticMethod was not mocked anymore by PowerMock).
As explained in (Mocking behaviour resets after each test with PowerMock) Powermock resets the mocks before each test.
For some reason it works the first time - there exists
an unresolved bug report for that issue (https://github.com/powermock/powermock/issues/398).
Its arguably bad design, but a way to do what you want is the following:
Instead of relying on the annotation set up the mocks manually.
private SomeClass attribute;
private SomeOtherClass testClass;
#Before
public void setUp() {
PowerMockito.mockStatic(StaticClass.class);
Mockito.when(StaticClass.staticMethod(anyString())).thenReturn(new SomeConcreteClass());
attribute = Mockito.mock(SomeClass.class);
testClass = new SomeOtherClass();
// assign mock manually
testClass.attribute = attribute;
}
The prefered way would be to supply the attribute using the constructor of SomeOtherClass, however since you seem to use a empty constructor
you will have to set the value from the outside. If the attribute instance is not accessible you might be forced to use reflections.
The cleaner way would be to refactor the constructor of you SomeOtherClass to not use a static method inside. Instead passing SomeConcreteClass as a parameter to the constructor is the way to go.
Some people even say you should not have any logic inside of a constructor.

Exception : mockito wanted but not invoked, Actually there were zero interactions with this mock

I have interface
Interface MyInterface {
myMethodToBeVerified (String, String);
}
And implementation of interface is
class MyClassToBeTested implements MyInterface {
myMethodToBeVerified(String, String) {
…….
}
}
I have another class
class MyClass {
MyInterface myObj = new MyClassToBeTested();
public void abc(){
myObj.myMethodToBeVerified (new String(“a”), new String(“b”));
}
}
I am trying to write JUnit for MyClass. I have done
class MyClassTest {
MyClass myClass = new MyClass();
#Mock
MyInterface myInterface;
testAbc(){
myClass.abc();
verify(myInterface).myMethodToBeVerified(new String(“a”), new String(“b”));
}
}
But I am getting mockito wanted but not invoked, Actually there were zero interactions with this mock at verify call.
can anyone suggest some solutions.
You need to inject mock inside the class you're testing. At the moment you're interacting with the real object, not with the mock one. You can fix the code in a following way:
void testAbc(){
myClass.myObj = myInteface;
myClass.abc();
verify(myInterface).myMethodToBeVerified(new String("a"), new String("b"));
}
although it would be a wiser choice to extract all initialization code into #Before
#Before
void setUp(){
myClass = new myClass();
myClass.myObj = myInteface;
}
#Test
void testAbc(){
myClass.abc();
verify(myInterface).myMethodToBeVerified(new String("a"), new String("b"));
}
Your class MyClass creates a new MyClassToBeTested, instead of using your mock. My article on the Mockito wiki describes two ways of dealing with this.
#Jk1's answer is fine, but Mockito also allows for more succinct injection using annotations:
#InjectMocks MyClass myClass; //#InjectMocks automatically instantiates too
#Mock MyInterface myInterface
But regardless of which method you use, the annotations are not being processed (not even your #Mock) unless you somehow call the static MockitoAnnotation.initMocks() or annotate the class with #RunWith(MockitoJUnitRunner.class).
#jk1 answer is perfect, since #igor Ganapolsky asked, why can't we use Mockito.mock here? i post this answer.
For that we have provide one setter method for myobj and set the myobj value with mocked object.
class MyClass {
MyInterface myObj;
public void abc() {
myObj.myMethodToBeVerified (new String("a"), new String("b"));
}
public void setMyObj(MyInterface obj)
{
this.myObj=obj;
}
}
In our Test class, we have to write below code
class MyClassTest {
MyClass myClass = new MyClass();
#Mock
MyInterface myInterface;
#test
testAbc() {
myclass.setMyObj(myInterface); //it is good to have in #before method
myClass.abc();
verify(myInterface).myMethodToBeVerified(new String("a"), new String("b"));
}
}
This exception can also be thrown if say, you expect thisMethod() to execute, but it didn't. It didn't because it's inside a condition that was not met.
For example, if you have some unit test that says verify thisMethod() is executed, but in fact, it was not because varX and varY are not equal.
//method expected to be called.
if( varX == varY){
thisMethod();
}
//test
Mockito.verify(foo).thisMethod();

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