Want to mock a method which is calling another class method - java

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.

Related

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 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 mock nested methods using PowerMock

Assume I have two classes A and B.
Class A{
public String methodA(String name) {
B b = new B();
b.methodB(name);
}
}
Class B{
public String methodB(String name) {
return name+name;
}
}
Now I want to mock methodA which has a nested method call to Class B.I have tried writing the below TestCase but getting methodNotImplementedException.
#Test
public void testCase() {
A a = new A();
B b = PowerMock.createPartialMock(B.class, "methodB");
EasyMock.expect(b.methodB(anyString())).andReturn("HELLO PTR");
PowerMock.replayAll();
String result = a.methodA("hello ptr");
assertEquals(result, "HELLO PTRHELLO PTR");
PowerMock.verifyAll();
}
Can anybody tell how to solve nested method calls using PowerMock..??
Thanx in advance
Several issues here.
First, don't use two mocking frameworks at the same time. There's no reason to expect when creating expectations in one framework, that the other would know about it.
Second, if, as stated, you want to mock methodA, supposedly as a part of a test of something that uses A, then there's no reason to mock anything from B, since the result of methodA is mocked, and will not invoke B.
Third, mock roles, not objects. Meaning, if object C accepts an A, it shouldn't get the concrete implementation, instead it should get the interface it uses. Then in the test, you mock that interface, not a class.
Given these, if you create an interface for A, and stub the response from that interface, your test will be much simpler, and you won't have to resort to these kinds of tools.
You can accomplish your goal by doing the following. Notice the whenNew call
#Test
public void testCase() {
A a = new A();
B b = PowerMock.createPartialMock(B.class, "methodB");
EasyMock.expect(b.methodB(anyString())).andReturn("HELLO PTR");
PowerMock.expectNew(B.class).andReturn(b);
PowerMock.replay(B.class);
String result = a.methodA("hello ptr");
assertEquals(result, "HELLO PTRHELLO PTR");
PowerMock.verifyAll();
}
you will also need to add #PrepareForTest(B.class) to the test class
Finally, you will need to add the api dependency
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>1.7.3</version>
<scope>test</scope>
</dependency>
If you want to mock methodA then there is no need to do anything with class B. Just do
#Test
public void testCase() {
A a = mock(A.class);
expect(a.methodA()).andReturn("HELLO");
replay(a);
// use the mock to test something
String result = a.methodA("hello ptr");
assertEquals(result, "HELLO");
verify(a);
}
But it looks like you want to test A and mock B. That's different. First, I would recommend refactoring. Even a really basic one like
public class A{
public String methodA(String name) {
B b = newB();
b.methodB(name);
}
protected B newB() {
return new B()
}
}
That way, you won't need PowerMock at all. You can do
#Test
public void testCase() {
A a = partialMockBuilder().addMockedMethod("newB").mock(A.class);
B b = mock(B.class);
expect(a.newB()).andReturn(b);
expect(b.methodB()).andReturn("HELLO");
replay(a, b);
String result = a.methodA("HI");
assertEquals(result, "HELLO");
verify(a, b);
}
And then, if you really need for some weird reason to mock new B(), yes, using Powermock.expectNew is the solution.
I resolved this by adding PowerMock.expectNew(B.class).andReturn(b); and #Mock annotation in the Test Class`
Complete Code;
public class A {
public String methodA(String name) {
B b = new B();
return b.methodB(name);
}
}
public class B{
public String methodB(String name) {
return name+name;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({ A.class, B.class })
public class TestCase {
#Mock
private B b;
#Test
public void testCase() throws Exception {
A a = new A();
PowerMock.expectNew(B.class).andReturn(b);
EasyMock.expect(b.methodB(anyString())).andReturn("HELLO");
PowerMock.replay(B.class, b);
String result = a.methodA("HI");
assertTrue(result != null);
assertEquals(result, "HELLO");
PowerMock.verify(B.class, b);
}
}

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

Testing Delegate Method with Mockito

In the class like the below the only tests required around doActionOne() and doActionTwo() are to ensure that they delegate to doAction() with the correct parameters.
As the delegate doAction(String a, int b, boolean c) method requires a lot of set-up then any solution should prevent the real method being called.
public class ClassUnderTest {
public void doActionOne(String a, int b) {
doAction(a, b, true);
}
public void doActionTwo(String a, int b) {
doAction(a, b, false);
}
public void doAction(String a, int b, boolean c) {
//already tested
}
}
Such a test would seem to require some kind of partial mock or spy however I am unable to get this correct.
The test should look something like the below although this approach doesn't work.
#Test
public void testDoActionOne(){
ClassUnderTest cut = Mockito.mock(ClassUnderTest.class);
//call the real method
when(cut.doActionOne("A1", 1)).thenCallRealMethod();
//test delegate called with correct params
verify(cut, times(1)).doAction("A1", 1, true); //fails wanted but not invoked
}
Not sure if I need something like:
http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/AdditionalAnswers.html#delegatesTo(java.lang.Object)
I know of two ways to do this. One means creating an anonymous inner class in which you override the method you don't want to test. This does not involve any Mockito magic. The other means using a Mockito Spy object, this is a proxy to a real instance, allowing you to specify stubbed behavior for some methods, and let the other methods fall through to the real instance.
Method 1, using an anonymous inner class:
public class MyTest {
private String a;
private String b;
private boolean c;
private ClassUnderTest instance = new ClassUnderTest() {
#Override
public void doAction(String a, int b, boolean c) {
MyTest.this.a = a;
MyTest.this.b = b;
MyTest.this.c = c;
}
}
public void test() {
// SETUP
String expectedA = "test value A";
String expectedB = "test value B";
boolean expectedC = true;
// CALL
instance.doActionOne(expectedA, expectedB);
// VERIFY
assertEquals(expectedA, a);
assertEquals(expectedB, b);
assertEquals(expectedC , c);
}
Method 2, using Mockito spy object:
#RunWith(MockitoJUnitRunner.class)
public class MyTest {
#Spy
private ClassUnderTest instance;
public void test() {
// SETUP
String expectedA = "test value A";
String expectedB = "test value B";
boolean expectedC = true;
doNothing().when(instance).doAction(expectedA , expectedB, expectedC);
// CALL
instance.doActionOne(expectedA, expectedB);
// VERIFY
verify(instance, times(1)).doAction(expectedA , expectedB, expectedC);
}
Because a spy is a Mockito controlled proxy you can also verify if methods were called on a spy, which is what you need here. You could also specify a stubbed return value for doAction (if it wasn't a void method):
// SETUP
doReturn("stubbed value").when(instance).doAction(expectedA , expectedB, expectedC);
It goes like this:
when(object.getFieldValue(attribute)).thenReturn(NESTED_ID);
verify(object, times(1)).getFieldValue(eq(attribute));

Categories