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
}
}
Related
I am testing a class that extends an abstract class. The concrete class members are Injected and when a method from the concrete class Mockito when-then returns null for the method call even though I have defined it in the test.
Abstract Class
public abstract class A {
#Inject
ObjA objA;
public String methodA() {
return objA.x()
}
// unimplemented methods
}
Class B
public class B extends A {
#Inject
ObjB objB;
public String methodB() {
String x = methodA()
return x;
}
}
TestClass
#RunWith(MockitoJUnitRunner.class)
public class BTest{
#Mock
ObjA objA
#Mock
ObjB objB
#InjectMock
B b;
#Before
public void init() {
Mockito.when(objA.x()).thenReturn("Hi");
}
#Test
public testBMethod() {
String x = b.methodB();
assertEquals(x,"Hi") // X is null even when, when then is defined for mocked object
}
}
Can someone let me know why the when-then didn't work?
I am writing JUnit for some legacy class which I can't change. The Problem which I am facing is as follows
public class B{
public String method2() {
//fetch some data from database and return it
}
}
public class A{
public String myMethod(B b) {
return b.method2();
}
}
how can I mock the call for method2 in junit using mockito
public class B2 extends B { // so, this is, in fact, an IS-A of B
public String method2() {
return "mockedResult";
}
}
In your test, you'll now have something like this:
#Test
public void testMethod() {
A toTest = new A();
assertEquals("mockedResult", toTest.myMethod(new B2());
}
This is the very simplistic way. But I would recommend to read up on a Mocking framework, such as Mockito for more complex scenario's.
https://www.baeldung.com/mockito-series
By using Mockito, for short, it would be something like this:
public class TestClass {
#Mock
private B b;
private A toTest = new A();
#Test
public void testMethod() {
when(b.method2()).thenReturn("mockedResult");
assertEquals("mockedResult", toTest.myMethod());
}
}
I have class TestME which has static main method. I need to avoid the call of b.cool method.
public class TestME {
public static int testme(String ...strings){
System.out.println(strings.length);
B b = new B();
b.cool();
return strings.length;
}
}
My B class is below
public class B {
public void cool(){
System.out.println("I am cool");
}
}
My Junit class for above TestMe class is below
#RunWith(MockitoJUnitRunner.class)
public class JunitTest {
#Spy
B b;
#InjectMocks
TestME test;
#Before
public void setUp(){
test = new TestME();
MockitoAnnotations.initMocks(this);
}
#Test
public void testMe(){
doNothing().when(b).cool();
Assert.assertEquals(2, test.testme("xyz", "omg"));
}
}
You may change your code from:
public class TestME {
public static int testme(String ...strings){
System.out.println(strings.length);
B b = new B();
b.cool();
return strings.length;
}
}
To the following:
public class TestME {
public static int testme(String ...strings){
System.out.println(strings.length);
B b = getInstanceOfB();
b.cool();
return strings.length;
}
static B getInstanceOfB(){
return new B();
}
}
Then in your test code you may spy on the class, stub getInstanceOfB() method to return mock object. Having this true b.cool would be never called in tests.
#RunWith(PowerMockRunner.class)
#PrepareForTest(TestME.class)
public class JunitTest {
#Before
public void setUp(){
B b = PowerMockito.mock(B.class);
PowerMockito.spy(TestME.class);
PowerMockito.when(TestME.getInstanceOfB()).thenReturn(b);
}
#Test
public void testMe(){
Assert.assertEquals(2, TestME.testme("xyz", "omg"));
}
}
You'll need a PowerMockito to accomplish that.
As you are calling static method no need to mock the TestMe. Simple call like TestMe.testme as below.
#Test
public void testMe(){
doNothing().when(b).cool();
Assert.assertEquals(2, TestMe.testme("xyz", "omg"));
}
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();
}
I want to test a method which creates an object of another class using it's parameterized constructor. Even though I've mocked the constructor of MyClass, it makes the third party library which is in constructor implementation and results in the error. I'm using Mockito/PowerMockito.
public class MyClass{
private MyObj obj;
MyClass (String profile)
{
//some 3rd party library call
obj = thridPartyLib.someMethod(profile);
}
public String someMethod(){
return obj.someExternalCall();
}
}
Class which I want to test
public class ClassTobeTested{
public void execute(){
//some code
// ......
MyClass myClass = new MyClass(profile);
myclass.someMethod();
}
}
What I tried so far - classUnderTest.execute() ends up calling the thridPartyLib.someMethod(profile); which is part of MyClass constructor.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = new ClassTobeTested();
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute(){
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
Your code will work only if you are working with a spy or mock of classUnderTest. Try this. This should work
#RunWith(PowerMockRunner.class)
#PrepareForTest( {MyClass.class, ClassTobeTested.class })
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = spy(new ClassTobeTested());
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute() throws Exception {
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
The pain might suggest another approach. Consider injecting a Factory into ClassTobeTested which knows how to create an instance of MyObj. For example:
class MyObjFactory {
MyObj create(String profile) {
return new MyClass(profile);
}
}
then
public class ClassTobeTested {
private final MyObjFactory factory;
public ClassTobeTested(MyObjFactory factory) {
this.factory = factory;
}
public void execute(){
//some code
// ......
// MyClass myClass = new MyClass(profile);
MyClass myClass = factory.create(profile);
myclass.someMethod();
}
}
so the unit test becomes simpler with only having to mock the Factory and have it return a mocked MyClass instance. Then it's simple to verify myclass.someMethod() was invoked as expected.