Mockito can't instantiate the class under test - java

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...)

Related

How to spy chained functions?

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.

How do you test method from extended class using Mockito?

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.

How to inject objects with list as an constructor argument using picocontainer?

I have a class which takes an list argument in its contructor:
public class A{
private List<B> bs;
public A(List<B> bs) {
this.bs= bs;
}
}
And I am adding this class in the container as follows:
A a = someObject.createData();
pico.addComponent(a);
But I am getting an exception:
org.picocontainer.injectors.AbstractInjector$UnsatisfiableDependenciesException: A has unsatisfied dependency 'java.util.List<B>' for constructor 'public A(java.util.List)' from org.picocontainer.DefaultPicoContainer#5b970f7:6<|
Does anyone know why this is happening?
Composition Code:
MutablePicoContainer pico = new DefaultPicoContainer();
SomeClass sc= new SomeClass();
A a = sc.createbData();
pico.addComponent(sc);
pico.addComponent("bs", a.getB());
pico.addComponent("a", A.class);
This error means that you don't have class 'B' registered in container.
There should be something like:
B b = new B();
pico.addComponent(b);
'B' can be an interface too, and Picocontainer supports injection of arrays with dependencies, so this will work:
public interface B {}
public class B1 implements B {}
public class B2 implements B {}
public class Test {
private List<B> stores;
public Test(List<B> stores) {
this.stores=stores;
}
}
pico.addComponent("b1",B1.class);
pico.addComponent("b2",B2.class);
pico.addComponent("test",Test.class);
Check also an official test case: https://github.com/picocontainer/picocontainer/blob/0f8172b7b12483920d0e3e2fcadb793d7ead4432/script/script-core/src/test/com/picocontainer/script/xml/XMLContainerBuilderTestCase.java#L868

How to mock chained dependencies in Java using Mockito

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();
}

spring test with difference bean service

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

Categories