Testing Delegate Method with Mockito - java

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

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