Does anyone know why in this example, when running "ATest", I get a null on the line "return b.getBAutoWiredObject().getString();"
Any insight on this would be appreciated.
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#Mock
private A a;
#Test
public void testMethod() {
String testedString = a.method();
assertEquals("blah", testedString);
}
}
#Service("A")
public class A {
public String method() {
B b = new B();
return b.getBAutoWiredObject().getString();
}
}
#Component
public class B {
#Autowired
#Qualifier("Bautowire")
private BAutoWiredObject bAutoWiredObject;
public BAutoWiredObject getBAutoWiredObject() {
return bAutoWiredObject;
}
}
#Service("Bautowire")
public class BAutoWiredObject {
private String string = new String("blah");
public void getString() {
return string;
}
}
Typically, the answer would be it's null because you created the B instance yourself. Spring is not involved in the least, so it hasn't autowired anything.
In this case, your A object is a #Mock and mocks are typically implemented to return null in any method that has a return type that is a reference type. Your method() implementation isn't actually getting called. The mock's implementation is.
This is all assuming your test would actually compile and was valid with a #Test annotated method.
assertEquals(testedString, "blah");
should be
assertEquals("blah", testedString);
The first argument should be the expected value and the second should be the actual value.
Related
I have an interface having default methods. These refer to non-default methods and I want to mock only those.
Example:
public interface InterfaceWithDefaultMethod {
public String getTestString();
public default String getCombinedString() {
return "Test" + getTestString();
}
}
I only want to mock getTestString()
EasyMock.mock(InterfaceWithDefaultMethod.class) does produce a mock class where all methods are mocked, i.e. getCombinedString is not being delegated to getTestString().
The problem can be solved by creating a dummy implementation of the interface and to partial-mock this dummy implementation.
private static class InterfaceMock implements InterfaceWithDefaultMethod {
#Override
public String getTestString() {
return null;
}
}
private InterfaceWithDefaultMethod testedInterface;
#Before
public void setup() {
testedInterface = createMockBuilder(InterfaceMock.class)
.addMockedMethod("getTestString")
.createMock();
resetToNice(testedInterface);
expect(testedInterface.getTestString()).andStubReturn("First");
replay(testedInterface);
}
My unit test:
#Test
public void testDoSomething() {
Method m = MyClass.class.getDeclaredMethod("methodToBeMocked");
m.setAccessible(true);
MyClass myClass = spy(new MyClass());
//m.invoke(myClass); // Calling this invokes the private method correctly
when(myClass.methodToBeMocked()).thenReturn("DummyReturn"); // This line throws the compiler error
myClass.doSomething(); // This is the method I'm trying to test
}
This is the compiler error I get:
The method methodToBeMocked() from the type MyClass is not visible
This is MyClass
public MyClass {
public MyClass() {}
public void doSomething() {
..
methodToBeMocked();
..
}
private String methodToBeMocked() { // Need to mock return value
return "Default";
}
}
The error message is self explanatory.
The method methodToBeMocked() from the type MyClass is not visible
The reason the method isn't visible is because it is a private method. Private methods can only be called within the class they are defined. If you want the method to be accessible from anywhere, make the method public.
public String methodToBeMocked() { // Need to mock return value
return "Default";
}
Information about method access specifiers
I need to inject a mock object into a method where a new MyClass object is instantiated.
private MyClass<?> c;
public void myMethod(final String s) {
c = new MyClass<>(s);
c.callToMock();
}
And the class I'm mocking has a constructor with a generic parameter.
public class MyClass<T> {
public MyClass(final T t) {
// do whatever
}
}
Now, in my test, I've created a mock for the class.
When new is called, it should inject that mock.
#RunWith (PowerMockRunner.class)
public class TestClass {
#SuppressWarnings ("unchecked")
public void myMethodTest() throws Exception {
MyClass<String> myMock = (MyClass<String>) EasyMock.createMock(MyClass.class);
PowerMock.expectNew(MyClass.class, "my argument")
.andReturn(myMock);
myMock.callToMock();
EasyMock.expectLastCall().once();
EasyMock.replay(myMock);
PowerMock.replayAll();
...
}
When I run the test, it doesn't catch the new call and just instantiates an actual MyClass object.
I don't know if it's not able to match the constructor or what.
Any help would be appreciated, thanks.
You need to add a #PrepareForTest(MyTestedClass.class) on your test class to prepare the tested class to mock the new.
Here is a fully working test:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyTestedClass.class)
public class TestClass {
#Test
#SuppressWarnings("unchecked")
public void myMethodTest() throws Exception {
MyClass<String> myMock = (MyClass<String>) EasyMock.createMock(MyClass.class);
myMock.callToMock();
PowerMock.expectNew(MyClass.class, "my argument")
.andReturn(myMock);
EasyMock.replay(myMock);
PowerMock.replayAll();
MyTestedClass tested = new MyTestedClass();
tested.myMethod("my argument");
}
}
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
private SomeDependency<T> obj;
#InjectMocks
private SomeClass mainObj;
#Test
public void dependencyShouldBeNotNull() {
//here I need one value of SomeDependency obj
assertEquals(2, mainObj.method())
}
#Test
public void dependencyShouldBeNull() {
//here I need SomeDependency obj to be null
assertEquals(1, mainObj.method())
}
Main class:
class SomeClass {
private SomeDependency<T> field;
public int method() {
if(field==null)
return 1;
else
return 2;
}
}
And my question: how to override value of mock according to different methods needs?
Edited
In main SomeClass I have code like this:
if (obj != null) {
//perform some actions
}
The easiest way to do it is with 2 test classes instead of one because when it executes your test methods it is already too late since the mock has already been injected (unless you use refection which should be avoided).
The first test
#RunWith(MockitoJUnitRunner.class)
public class Test1 {
#Mock
private SomeDependency<T> obj;
#InjectMocks
private SomeClass mainObj;
#Test
public void dependencyShouldBeNotNull() {
//here I need one value of SomeDependency obj
assertEquals(2, mainObj.method());
}
}
The second test
#RunWith(MockitoJUnitRunner.class)
public class Test2 {
#InjectMocks
private SomeClass mainObj;
#Test
public void dependencyShouldBeNull() {
//here I need SomeDependency obj to be null
assertEquals(1, mainObj.method());
}
}
If you want to do it with only one test class, it is still possible but it is more like a hack because you want a conditional injection which is not a conventional approach, so you will need to inject the mocks programmatically with MockitoAnnotations.initMocks(obj).
Instead of injecting the mocks directly into the test class, we need to rely on wrapper classes that will contain or not the field obj, if not present nothing will be injected so it will be null otherwise you will have a mock injected.
public class TestInjectMocks {
/**
* Small interface that will be implemented by the wrapper classes
* only used to get the main class
*/
public interface TestConfig {
SomeClass getSomeClass();
}
#Test
public void dependencyShouldBeNotNull() {
// This class will allow to get an instance of SomeClass
// with the field injected
TestConfig obj = new TestConfig() {
#Mock
private SomeDependency<T> obj;
#InjectMocks
private SomeClass mainObj;
#Override
public SomeClass getSomeClass() {
return mainObj;
}
};
MockitoAnnotations.initMocks(obj);
SomeClass mainObj = obj.getSomeClass();
//here I need one value of SomeDependency obj
assertEquals(2, mainObj.method());
}
#Test
public void dependencyShouldBeNull() {
// This class will allow to get an instance of SomeClass
// without the field injected
TestConfig obj = new TestConfig(){
#InjectMocks
private SomeClass mainObj;
#Override
public SomeClass getSomeClass() {
return mainObj;
}
};
MockitoAnnotations.initMocks(obj);
SomeClass mainObj = obj.getSomeClass();
//here I need SomeDependency obj to be null
assertEquals(1, mainObj.method());
}
}
NB: As we call MockitoAnnotations.initMocks(obj) explicitly the annotation #RunWith(MockitoJUnitRunner.class) is not needed anymore.
Based on what you've posted, I recommend using the 'Mockito.when()' method for the first method, then setting obj = null; as #Seelenvirtuose suggests. If that doesn't work, you might want to pass in a different Mocked out object which is initialized to null. See this example.
I am trying to test a method whom depending on some conditions will execute its code or its super class's one.
Here is the code of the class and its parent:
public class ParentClass {
public Object doStuff(Parameters parameters) {
// do some business stuff
return parentResult;
}
}
The inherited class's one:
public class InheritedClass extends ParentClass {
#Override
public Object doStuff(Parameters parameters) {
if (parameters.getCondition()) {
return super.doStuff(parameters);
}
//do some business stuff
return inheritedResult;
}
}
So, when trying to test the case when the parameters.getCondition() is true, I have to mock the call on the super method and verify it.
But when I do this (mocking the call for the super.doStuff()), I also mock the call to the InhertitedClass.doStuff().
Here's the solution I tried:
#RunWith(MockitoJUnitRunner.class)
public class InheritedClassTest {
#Mock
private Parameters parameters;
#Spy
private InheritedClass inherited = new InheritedClass();
#Test
public void testDoStuff(Object parameters) throws Exception {
given(parameters.getCondition()).willReturn(true);
doCallRealMethod().doReturn(value).when(inherited).doStuff(parameters);
Mockito.verify(inherited, times(2)).doStuff(parameters);
}
}
I also tried this stubbing:
when(inherited.doStuff(parameters)).thenCallRealMethod().thenReturn(value);
and this one:
given(((ParentClass)inherited).doStuff(parameters)).willReturn(value);
In all this cases, the code of the parent class was really executed.
So, I was wondering if there is any efficient way to mock the call of the super class method using mockito?
You can use Mockito's spy(), which you already tried to do. But I think a different way of using spy() will make it work.
ParentClass.java
public class ParentClass {
public String doStuff(final String parameters) {
return "parent";
}
}
InheritedClass.java
public class InheritedClass extends ParentClass {
#Override
public String doStuff(final String parameters) {
if (parameters.equals("do parent")) {
return super.doStuff(parameters);
}
return "child";
}
}
InheritedClassTest.java
public class InheritedClassTest {
#Test
public void testDoStuff() throws Exception {
final InheritedClass inheritedClass = Mockito.spy(new InheritedClass());
Mockito.doReturn("mocked parent").when((ParentClass)inheritedClass).doStuff(Mockito.eq("do parent"));
final String result = inheritedClass.doStuff("do parent");
assertEquals("mocked parent", result);
assertNotEquals("parent", result);
final String resultChild = inheritedClass.doStuff("aaa");
assertEquals("child", resultChild);
}
}
However, I do not think using spy() is a good practice. I would personally refactor your code.