How do you test method from extended class using Mockito? - java

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.

Related

Want to mock a method which is calling another class method

I am new to mockito using it for unit testing. I need some help to understand mock a method.I have a method - method1() of class A which needs to be tested .Here i want to verify that execute() is executed (Interaction testing).Below is the method.
class A{
void method1(){
B b = new B(org_id);
b.execute();
}
}
Class B {
B(String orgId){
this.orgId = org_id;
}
void execute(){
String x = Dependency.m1();
String y = Dependency.m2();
}
static class Dependency{
public String m1(){
return K.someText();
}
public String m2(){
return K.someText();
}
}
}
Could anyone help me how to achieve it?TIA
As here you are not using any dependency injection, you cannot mock and inject that object into the test class using mocikto.
You can look at this answer here :-
Java Mock object, without dependency injection
Make B an instance variable of A, add a constructor for A, pass the mock to constructor.
class A{
B b;
public A(B b){
this.b = b;
}
}
in test class
A a = new A(Mockito.mock(B.class));
Since you create a new instance of B, you could parameterize A with a Function<String, B> (a factory method, or just B::new which you can the mock in your test.
class A {
final Function<String, B> bCreator;
A(Function<String, B> bCreator) {
this.bCreator = bCreator;
}
void method1(){
B b = bCreator.apply(orgId);
b.execute();
}
}
// test
B b = mock(B.class);
Function<String, B> bCreator = mock(Function.class);
when(bCreator.apply(any()).thenReturn(b);
A a = new A(bCreator);
a.method1();
verify(b).execute();
The test whether B::execute works correctly (ie calls the appropriate dependency methods) should be done in another test since it's another unit.

how to stub a method in a class which is called from another class

public class A {
.
.
.
public static String methodA() {
String x = new B().methodX();
return x + "how are ya?";
}
}
public class B {
.
.
public String methodX() {
return "Hello!";
}
}
#Test
public void testGreeting() {
final B b = Mockito.spy(new B());
Mockito.when(b.methodX()).thenReturn("Hi!");
String greetings = A.methodA();
// greetings -> "Hello" but i want it to be "Hi!".
}
I'm not able to get my method to return the desired value.
Above implementations shows how I have written my test, but it's not working.
What am i doing wrong here?
Yet to clarify given answers: your mistake is that you do not actually use that spy/mock anywhere.
In your class A you have a static method where a new B is always instantiated instead of using your spy:
String x = new B().methodX();
Spy does not make class somehow globally spied but creates just one instance that is spied and can be mocked. And yet again: this new B() is not a spy nor mock.
One possible working solution would be to change your design a bit (as already suggested) and let Mockito inject this spied B in an instance of A:
#RunWith(MockitoJUnitRunner.class)
public class TestClass {
public static class AlternativeA {
// this B can be injected and replaced with a spy or mock
private B b = new B();
// get rid of static to use spied B
public String methodA() {
String x = b.methodX();
return x + "how are ya?";
}
}
// Using annotations to create and inject mocks
#Spy
private B b;
#InjectMocks
private AlternativeA a;
#Test
public void testGreeting() {
Mockito.when(b.methodX()).thenReturn("Hi!");
String greetings = a.methodA();
}
}
To complete the answer writen by wakio, instead of your code, you can write :
public class A {
private B b;
public String methodA() {
String x = b.methodX();
return x + "how are ya?";
}
public void setB(B b) {
this.b = b;
}
}
public class B {
public String methodX() {
return "Hello!";
}
}
#Test
public void testGreeting() {
B b = Mockito.mock(B.class);
Mockito.when(b.methodX()).thenReturn("Hi!");
A a = new A();
a.setB(b);
String greetings = a.methodA();
// The result will be "Hi!"
}

How to mock method calls of some object which is passed as method parameter of method under JUnit Test

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

How to mock a function call while initializing a variable in #Tested testObject in junit

I have a class A which has a private integer member b. Here is the structure of the class:
public class A {
private int b= Integer.parseInt(C.getValue(anyString));
public int getB() {
return b;
}
public void setB(int b) {
this.b= b;
}
}
I am testing some method of this class using jmockit with junit4 `
public class ATest {
#Tested
A a;
#BeforeClass
public void setUp() {
//mock C.getValue
}
#Test public void test1() {
//some test code
}
}
but I am unable to mock the call (C.getValue(anyString)) thus the test fails while building the project. I have tried using #Before and #BeforeClass but none of those executed even once. Please suggest a way out.
Considering I can't change the main class A.
First of all the way you are doing this is not very good since you are not able to control values that are returned from class C. But if you want to keep your code like this, you can extract
C.getValue(anyString)
to new protected function in your class
public class A {
private int b= Integer.parseInt(getValue(anyString));
public int getB() {
return b;
}
public void setB(int b) {
this.b= b;
}
protected String getValue(String anyString) {
return C.getValue(anyString);
}
}
After that you can in your test clas can create new private class that extends class A and then override its
getValue(String anyString)
function.
In test class:
public class ATest extends A {
#Override protected String getValue(String anyString) {
return "return 1 or any other string reperesentation of number";
}
}
Function getValue(String anyString) in that, let's call it AText class, then can return value of your choice. This way you'll have controlled environment and you can test this new ATest class.
The root cause is that you code violates the Single Responsibility/Separation of Concerns principle. It is also a case of the work in constructor code smell.
Your class A pretty much looks like a Data Transfer Object (DTO) Its only responsibility is to carry data. Fetching the data from the database should be done by some framework outside the class and the data should be passed in from the outside.
Problem solved. Just needed to add static to the setUp() method in #BeforeClass and mocked the call. Not the right way to do it but I was only allowed to change the test class.

How to override a method in unit tests that is called from which the class being tested

I am testing a class A's function func1.
Func1 has a local variable of Class B and calls B's function func2. Code looks something like this:
public Class A
{
public func1()
{
B object = new B();
int x = object.func2(something);
}
}
When I am testing func1 in its unit tests, I don't want func2 to get called.
So I am trying to do something like this in the test:
B textObject = new B()
{
#override
int func2(something)
{
return 5;
}
}
But it is still calling the func2 in the class B. Please suggest how to handle this.
If you want to override the new B() constructor call - place it in an own method.
public Class A
{
public func1()
{
B object = newB();
int x = object.func2(something);
}
protected B newB(){
return new B();
}
}
In your test you can then override the B constructor call.
public class APartitialMock extends A {
protected B newB(){
return new BMock();
}
}
public class BMock extends B {
int func2(something) {
return 5
}
}
Then use APartitialMock to test the func1 with your kind of B.
PS If you can or want to use a framework take a look at powermock - Mock Constructor
I can make B as a class variable in A but that doesn't seem to help
either. What would you suggest in this case?
If you make B as a class variable, then you can mock B, and "swap" it in the tested object of A.
Maybe not very elegant, but quick and simple.
An example:
public class B {
int func2(int something){
return 3*something;
}
}
public class A
{
// declare it as protected - a test need to have access to this field to replace it
protected B object = new B();
public int func1()
{
int x = object.func2(22);
return x;
}
}
And a test:
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.Test;
public class ATest {
#Test
public void test() {
A myA = new A();
B myB = mock(B.class);
// dummy function
when(myB.func2(anyInt())).thenReturn(20);
// replace B with mocked B
myA.object = myB;
int actual = myA.func1();
assertEquals(20, actual);
}
}

Categories