1

I unable to mock an instance of a Class which is being created inside the method which I am trying to test. Below is an example to illustrate the issue.

Class and Method Being tested:

// class being used in the class to be tested
public class SomeOtherClass{

public ResponseObject addObject(Request dtoObject){
    /// Some business logic goes here

    return reponseObject;
  }
} 

// Class to be tested
public class ClassToBeTested {

public ClassToBeTested() {}

public void myMethodToBeTested() {
    SomeOtherClass otherClassObject = new SomeOtherClass();

    // Here I want mock the otherClassObject and also addObject method 
    // Eventhoug I mocked it seems to me that as otherClassObject is being created here locally 
    // I am unable to mock it.
    ReponseObject reponseObject = otherClassObject.addObject(dtoObject);

    // do some other stuff using the reponseObject
  }
}

Test Class:

public class TestClassToBeTested {
@Tested private ClassToBeTested classBeingTested;
@Injectable SomeOtherClass innerSomeOtherClass;

RequestObject myRequestObject = new RequestObject();
myRequestObject.setSomevalue1("1");
myRequestObject.setSomevalue2("2");

ResponseObject myMockResponseObject = new ResponseObject();
myMockResponseObject.setResultCode(SUCCESS);

@Test
public void shouldTestSomething() {
    new NonStrictExpectations(){{
        // Here I am returning the mocked response object.
        SomeOtherClass.addObject((SomeOtherClass)any);
        result =myMockResponseObject;
    }};   

    classBeingTested.myMethodToBeTested(); 

    // ... 
 }
}

I mocked the SomeOtherClass and its method but no luck, not sure the proper way to mock it using JMockit.

SomeOtherClass & its method addObject

Even though I mocked it in the Test class, but it gets cleared in the method to be tested. I found similar question being asked HERE, but the solution uses some other unit test framework Mockito. I am struggling to find similar solution using JMokcit. Could any one help me to find the solution for this?

Below is my updated code sample

Class and Method Being tested:

// This is the class to be tested
public class MyMainClass {

public ResponseObject addItem(ProductList products) {

ResponseObject responseObject = new ResponseObject();

OtherService otherService = new OtherService();

List<Product> productList = new ArrayList<Product>();
productList = products.getProducts();

for (int i = 0; i < productList.size(); i++) {
  Product product = otherService.addProduct(productList.get(i));
  System.out.println("model.Product " + product.getName() + " added 
  successfully");
}

responseObject.setResponseCode("1");
responseObject.setResponseMessage("Success");
return responseObject;
 }
}

// Some other service internally used by MyMainClass
public class OtherService implements IService{
 public Product addProduct(Product product){

  // Some business logic to process the product
  System.out.println("Adding product :"+product.getName());

  return product;
  }
}

// Interface implemented by OtherService
public interface IService {

 Product addProduct(Product product);

}

// Sample ResponseObject class 
public class ResponseObject {

String responseCode;
String responseMessage;

public String getResponseMessage() {
   return responseMessage;
}

public void setResponseMessage(String responseMessage) {
   this.responseMessage = responseMessage;
}

public String getResponseCode() {
  return responseCode;
}

public void setResponseCode(String responseCode) {
  this.responseCode = responseCode;
}
}

Test Class:

public class MyMainClassTest {

@Tested
MyMainClass myMainClass;

@Mocked
IService otherService;

private List<Product> myProducts = new ArrayList<Product>();

@Before
public void init(){

  Product product1 = new Product();
  product1.setName("Test1");
  product1.setPid(1);
  product1.setPrice(100.00);
  myProducts.add(product1);
  Product product2 = new Product();
  product2.setName("Test2");
  product2.setPid(2);
  product2.setPrice(200.00);
  myProducts.add(product2);
}

@Test
public void addItem_Test() throws  Exception{
 myMainClass = new MyMainClass();

 new NonStrictExpectations(){{
  otherService.addProduct((Product)any);
  returns(myProducts.get(0));
 }};

 ProductList productList = new ProductList();
 productList.setProducts(myProducts);
 ResponseObject responseObject = myMainClass.addItem(productList);

 Assert.assertEquals(responseObject.getResponseMessage(),"Success");
}
}

After trying and analyzing the problem I found the what went wrong. I will update the solution in the answer section so that it would be helpful others also.

Thanks.

Rogério
  • 16,171
  • 2
  • 50
  • 63
Pabdev
  • 406
  • 3
  • 14
  • 1
    Don't create `SomeOtherClass` inside `myMethodToBeTested()`, but create it at level above and send as parameter `myMethodToBeTested(otherClassObject)`. In this case you'll be able to mock it in tests. – Bor Laze May 31 '19 at 16:26
  • @BorLaze thanks for your reply. But there is no other way without changing the class to be tested to mock the SomeOtherClass like the solution suggested in the https://stackoverflow.com/questions/25069564/mocking-objects-created-inside-method-under-test using JMockit? – Pabdev May 31 '19 at 17:32
  • I tried to write the test for your code, but it's impossible, since it's so full of errors... (doesn't compile, calls different methods where it apparently should be the same one, etc.) If you could clean it up, that would help. – Rogério Jun 02 '19 at 19:04
  • @Rogério sorry for that code. I have updated my question with proper working sample code. – Pabdev Jun 03 '19 at 12:03

2 Answers2

1

You simply use @Mockedfor that. Check the JMockit tutorial or the API documentation, there are plenty of examples.

Rogério
  • 16,171
  • 2
  • 50
  • 63
  • thanks for the reply. Infact I tried @ Mocked also but still it didnt work. As soon as i enters the myMethodToBeTested method the mocked object has no effect and object which is being created in this method overrides the mocked object. But as suggested by BorLaze when I pass the otherClassObject as parameter to the myMethodToBeTested then it works. – Pabdev Jun 01 '19 at 04:09
  • You are right @Mocked actually works but in my case I Mocked the Service interface (IService) hence it was not working. So I should mock the implemented class rather than mocking the interface. After mocking the implemented class OtherService. Thanks. I will update accordingly. – Pabdev Jun 03 '19 at 12:16
0

After trying and debugging again I found what was wrong. What I was doing wrong is mocking the interface (IService) and hence it was not working. When I changed it to mock the implemented class (OtherService) then it worked properly.

So in the Test class I replaced

@Mocked IService otherService;

with

@Mocked OtherService otherService;

After this change my problem got resolved.

Thanks

Pabdev
  • 406
  • 3
  • 14