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);
}
}
Related
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.
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!"
}
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.
I am trying to write a test with stubbing but mocking one of the methods does not happen as expected.
class A {
public static getInstance(){
return new A();
}
public String getConn(){
return "Hello";
}
}
class B {
public String createConn(){
A instance = A.getInstance();
return instance.getConn();
}
}
My Test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class TestClassB{
#Spy
B classB = new B();
#Test
public void testConn(){
PowerMockito.mockStatic(A.class);
given(A.getConn()).thenReturn("Welcome");
assertEquals("Welcome", classB.createConn());
}
I want to create a test on Class B, createConn method, and when I get the connection, instead of "Hello", I want to receive "Welcome" using mockito?
I found the solution of the problem.
PowerMockito.mockStatic(A.class);
PropertyManager mock = PowerMockito.mock(A.class);
given(A.getInstance()).willReturn(mock);
given(mock.getConn()).willReturn("Welcome");
assertEquals("Welcome", classB.createConn());
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());
}
}