I have Class A, which has a dependency on class B. And class B has again has a dependency on class C. Structure looks like:
Class A(){
#Autowired
private B b;
public void someMethod(){
b.callAnotherMethodAndGetValue();
}
}
Class B(){
#Autowired
private C c;
public void callAnotherMethodAndGetValue(){
c.callAnother();
}
}
Class ATest(){
#Spy
private B b;
public void someMethod(){
// it goes into this method, and throws null pointer exception at
// c.callAnother(); as c is null.
b.callAnotherMethodAndGetValue();
}
}
Is there any way I can let the stack flow to c.callAnother from Test Cases. Without doing when then at b.callAnotherMethodAndGetValue();
You need to mock C: and not spy on b:
#Mock
C c;
#InjectMocks
B b;
#Test
public void someMethod(){
b.callAnotherMethodAndGetValue();
}
Off cause you'd make your life easier if you used constructor injection!
I am writing the test cases for Class A. Inside Test For Class A , I should do #InjectMocks A a and should do a.someMethod() – Jyoti Yadav
Then the test should look like this:
#Mock
B b;
#InjectMocks
A a;
#Test
public void someMethod(){
a.someMethod();
}
Related
I have a structure like the code below:
public class MyClass {
private A myA;
public callSomeMethod() {}
}
public class A {
private B myB;
// getter and setter
}
public class B {
private BigDecimal C;
// getter and setter
}
And in my tests I have something like that:
public class MyClassTest {
#InjectMocks
private MyClass underTest = new MyClass ();
#Spy
private A a;
#Test
public void shouldPass() {
X x = new X();
x.setSomething(10);
// given
stubData();
doReturn(x).when(a).getB().getC(); // <-- Here I got the error
// when
MyClass myc = underTest.callSomeMethod();
// then
assertEquals(myc.getC, 10);
}
}
How to use doReturn to "mock" the value when I a chained methods (in the example: getC) is called?
a may be a spy, but the result of its getB() method isn't. You'll need to set that up.
Something like this should work to get getB() to return a spy:
doAnswer(i -> spy(i.callRealMethod())).when(a).getB();
That returns a different spy each time getB() is called, so if that method always returns the same instance, you can cache it:
B b = spy(a.getB());
doReturn(b).when(a).getB();
You can put all of this in an #BeforeEach method so that you don't have to repeat this for every test.
I have a class A that extends from B. B has method called doB().
In my test, I want to return A when doB() is called.
Class B:
public String doB() {
return "B";
}
Class A:
public class A extends B {
public String doA() {
String A = doB();
return A;
}
}
In my unit test, I want to do something like:
#Mock
private A a;
#Test
public void test() {
when(a.doB()).thenReturn("PASS");
a.doB();
//check if it is "PASS"
}
However, it doesn't intercept when it calls doB(). Is this possible? If not, what is the best way to test this?
Perhaps favour composition over inheritance. In other words, instead of A extending B, A should use B. So B becomes A's collaborator.
For example:
public class B {
public String doB() {
return "B";
}
}
public class A {
private B b;
public A(B b) {
this.b = b;
}
public String doA() {
String a = b.doB();
return a;
}
}
So your unit test would look something like:
public class MyTest {
#Mock
private B b;
#InjectMocks
private A a;
#Test
public void test() {
when(b.doB()).thenReturn("PASS");
a.doA();
//check if it is "PASS"
}
}
This is an example of how TDD can contribute to good design.
Since you are mocking class A, the method will not really be executed, which means there is no call to doB inside youre mock execution.
you should either setup your mock to call the real method
when(a.doA()).thenCallRealMethod();
verify(a,times(1)).doB();
or use a Spy instead of a Mock.
I have a class that, when being constructed, cannot call a certain method.
public class ClassA() {
#NonNull
private ClassB b;
public ClassA() {
this.b = (new ClassC()).mymethod();
}
}
I need to test ClassA without calling ClassC().mymethod() because calling it will throw an error. What is the best approach to do so? I tried #InjectMocks for ClassA with #Mock ClassC but it gives me null exceptions.
You have to refactor your class to make it more testable. The additional two constructors in the following code snipped can be used in tests with mocks for ClassC or ClassB:
public class ClassA() {
#NonNull
private ClassB b;
public ClassA {
this(new ClassC());
}
public ClassA(ClassC c) {
this(c.mymethod());
}
public ClassA(ClassB b) {
this.b = b;
}
}
Example test case:
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
public class ClassATest {
#Test
public void test() {
ClassB b = mock(ClassB.class);
// ... setup your mock for b
ClassC c = mock(ClassC.class);
when(c.mymethod()).thenReturn(b);
ClassA a = new ClassA(c);
// ... call the method of "a" you want to test
}
}
You can use CALLS_REAL_METHODS to avoid call constructor of ClassA
#RunWith(MockitoJUnitRunner.class)
public class ClassATest {
#Mock
private ClassB b;
private ClassA classA;
#Before
public void setUp() {
classA = mock(ClassA.class, org.mockito.Mockito.CALLS_REAL_METHODS);
whitebox.setInternalState(classA, "b", b);
}
#Test
public void shouldDoSomething() {
// your test
}
}
I want to test service A, which has a method methodA1, A refers to a service B, which has a method methodB1,
In methodB1 is called in methodA1,
#Service
class A{
#Autowired
B b;
void methodA1{
....
b.methodB1();
.....
}
}
#Service
class B{
void methodB1{
....
}
}
Now, I want to test methodA1, but the methodB1 need to be overridden, so I create a new class BMock;
#Service("bMock")
class BMock execute B{
#Override
void methodB1{
....
}
}
Test case like this:
class testClass extends springTest{
#Autowired
A a;
#Autowired
#Qualifier("bMock")
B b;
#Test
public void testMethodA1(){
a.methodA1();
}
}
actually, the methodA1 always call methodB1 in class B, I want it to call BMock in test case, how to do it?
If you have a setter for b in class A, override it explicitely in test :
class testClass extends springTest{
#Autowired
A a;
#Autowired
#Qualifier("bMock")
B b;
#Test
public void testMethodA1(){
a.setB(b);
a.methodA1();
}
}
If you have no setter (and do not want to create it), you can use reflection :
Field bField = A.getDeclaredField("b");
fField.setAccessible(true);
fField.set(a, b);
it breaks isolation of private fields but may be acceptable for a test.
Spring Re-Inject can be used to replace beans with mocks in test environment.
#ContextConfiguration(classes = {ReInjectContext.class, testClass.TextContext.class})
class testClass extends springTest {
#Autowired
A a;
// Spring context has a bean definition for B, but it is
// overridden in the test's constructor, so BMock is created
// instead of B. BMock gets injected everywhere, including A and the
// test
#Autowired
B b;
public testClass() {
// Replace bean with id "b" with another class in constructor
// "b" is bean ID that Spring assigns to B
ReInjectPostProcessor.inject("b", BMock.class);
}
#Test
public void testMethodA1(){
a.methodA1();
}
// If A and B are already the part of Spring context, this config
// is not needed
#Configuration
static class TestContext {
#Bean public A a() { return new A(); }
#Bean public B b() { return new B(); }
}
}
And remove #Qualifier and #Service from BMock
I've got three classes A, B and C:
public class A {
#Autowired
private B someB;
private C someC = someB.getSomeC();
}
#Service
public class B {
C getSomeC() {
return new C();
}
}
public class C { }
Now if I write a unit test for A which looks like:
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#InjectMocks
private A classUnderTest;
#Mock
private B someB;
#Mock
private C someC;
#Test
public void testSomething() {
}
}
Mockito is not happy with this:
org.mockito.exceptions.base.MockitoException:
Cannot instantiate #InjectMocks field named 'classUnderTest' of type 'class my.package.A'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : null
If I remove the call in class A, such that class A looks like the following:
public class A {
private B someB;
private C someC;
}
, Mockito is able to instantiate the classUnderTest and the test runs through.
Why is this the case?
edit: Using Mockito 1.9.5
Well this is always going to fail:
public class A {
private B someB;
private C someC = someB.getSomeC();
}
You're trying to call getSomeC() on a value which will always be null... that will always thrown NullPointerException. You need to fix A to handle the dependencies better. (Personally I'd take them as constructor parameters, but there are other options of course...)