Mock inner final object - java

I am trying to write a test for pre-existing class.
class ClassToBeTested {
private final Obj1 a;
ClassToBeTested(String anotherVariable) {
a = new Obj1(anotherVariable);
}
public void methodToBeTested() {
if(invokeSomeOtherMethod()) {
a.getAnotherVariable().doSomething();
}
}
public boolean invokeSomeOtherMethod() {
// return true or false based on some logic
}
Obj1 getObj1() {
return a;
}
}
Below is my Test Class:
class TestClass {
#Test
public void testMethod() {
ClassToBeTested x = new ClassToBeTested("someString");
ClassToBeTested spyX = spy(x);
doReturn(false).when(spyX).invokeSomeOtherMethod();
spyX.methodToBeTested();
verify(spyX, times(1)).getObj1().doSomething();
}
}
This is my understanding:
Since the obj1 is private final object which is created in the class constructor, it neither be directly accessed in the test method nor force the spyObject to use a mocked version of obj1.
Also since verify() requires mocked version of obj1, it throws me an error:
Wanted But Not invoked: x.getObj1(), however there are otherInteractions with this mock: x.invokeSomeOtherMethod()
Is my understanding wrong? What would be the way to test testMoethod()?

You seem to not understand how to do proper dependency injection. You don't need to change all your code in order to make it easier to test - just use constructor telescoping for example:
class ClassToBeTested {
private final Obj1 a;
public ClassToBeTested(String anotherVariable) {
this(new Obj1(anotherVariable));
}
ClassToBeTested(Obj1 a) {
this.a = a;
}
Done. Now you have a package-protected constructor that you can use to insert an instance of a directly. And all your other production code can stay like it is.
In other words: don't "fix" your design problems by using mocking framework tricks.

Related

How to mock a new object creation in Javaa

I am trying to mock a new object creation in java, but unable to do so.
this is the code.
public class testClass() {
private final MyObject myobject;
private SecondObject secondObject;
public testClass(MyObject myObject) {
this.myObject = myObject;
}
public void init() {
secondObject = new SecondObject(myobject,100,100);
}
}
Please explain how to mock secondObject in this example.
The design of testClass makes it difficult to test (ironically). It has a dependency on a second class that is hidden. Your best option is to expose this dependency:
interface SecondObjectCreator {
SecondObject create(TestClass obj, int val1, int val2);
}
class TestClass {
public TestClass(MyObject obj, SecondObjectCreator creator);
}
This redesign makes the code easy to test as you can inject a mock that behaves in a variety of ways.

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.

Java method simulation

As part of behavioral testing I need to simulate the method call in a given class.
So say if I have a class like:
class A {
public void abc(){
new classB().getData();
}
public void xyz( boolean callabc){
if (callabc) {
abc();
}
}
So my requirement is to first find all methods in class A then find which method is making which call like xyz is calling abc which is calling class B getData method.
Is it possible to get all these data in Java?
You can transform your code into something like this:
public class A {
private final ClassB b;
public A(ClassB b) {
this.b = b;
}
public void abc(){
b.getData();
}
public void xyz( boolean callabc){
if (callabc) {
abc();
}
}
}
Then you can pass mock implementation of class B during tests. Then you can verify that some method was invoked on mock with specific parameters with mockito library:
http://static.javadoc.io/org.mockito/mockito-core/2.3.0/org/mockito/Mockito.html#1

How to replace method invocation with mock?

I have a class with two methods. I want to replace invocation of second method with expected result.
Here is my class under test
public class A {
public int methodOne() {
return methodTwo(1);
}
public int methodTwo(int param) {
// corresponding logic replaced for demo
throw new RuntimeException("Wrong invocation!");
}
}
And test
public class ATest {
#Test
public void test() {
final A a = spy(new A());
when(a.methodTwo(anyInt())).thenReturn(10);
a.methodOne();
verify(a, times(1)).methodTwo(anyInt());
}
}
Why I'm get an exception when start the test?
Two things that will help you here. First, from the documentation it seems you need to use the do*() api with spy() objects. Second, to call the "real" method you need to declare it specifically using doCallRealMethod()
Here's the updated test that should work for you:
public class ATest {
#Test
public void test() {
final A a = spy(new A());
doReturn(10).when(a).methodTwo(anyInt());
doCallRealMethod().when(a).methodOne();
a.methodOne();
verify(a, times(1)).methodTwo(anyInt());
}
}

Mocking a call on a public method of an abstract class without subclassing the abstract Class, using mockito prefererably

I am writing an unit testing using JUNIT + Mockito to test a method like :
public someObject methodUnderTest(){
SomeObject obj = SomeAbstractClass.someMethod();
if(obj!=null){
obj.someOtherMethod();
}
return someThing;
}
And I would like to mock the call on abstract Class "SomeAbstractClass" mentioned in above code fragment so i can verify call on "obj" like :
verify(SomeAbstractClass).someMethod();
verify(obj).someOtherMethod();
I have tried using mockito features like :
Mockito.CALLS_REAL_METHODS
Mockito.RETURNS_MOCKS
but they don't work due to dependencies not available to the SomeAbstractClass.
Note:
1) SomeObject is an Interface.
2) I need a technique to test above code fragment. I am constrained to use the above code fragment and cannot change the code fragment.
You can use PowerMock to mock static and final methods.
It sounds like the problem is that your use of CALLS_REAL_METHODS is applying to the entire class, where you really want to mock out specific methods (i.e. make a "partial mock"). You have two options here, one using thenCallRealMethod, and one using CALLS_REAL_METHODS and then specifically mocking the calls you need:
public void testMethodUnderTest_mockSpecificThings() {
SomeAbstractClass myAbstractClass = Mockito.mock(SomeAbstractClass.class);
SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
when(myAbstractClass.someMethod()).thenReturn(foo);
when(myAbstractClass.methodUnderTest()).thenCallRealMethod();
myAbstractClass.methodUnderTest();
verify(myAbstractClass).someMethod();
verify(myObject).someOtherMethod();
}
public void testMethodUnderTest_makeSpecificRealCalls() {
SomeAbstractClass myAbstractClass =
Mockito.mock(SomeAbstractClass.class, CALLS_REAL_METHODS);
SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
// overrides the default answer
when(myAbstractClass.someMethod()).thenReturn(myObject);
myAbstractClass.methodUnderTest();
verify(myAbstractClass).someMethod();
verify(myObject).someOtherMethod();
}
Be forewarned that SomeAbstractClass is never actually instantiated, so if you rely on any behavior in the abstract class constructor, like variable initialization--including inline initialization where the fields are declared--you will need to make those calls explicitly yourself.
Assumption: if you write unit test, I guess you still can modify tested method a bit.
Solution:
extract static method call to overridable method:
public someObject methodUnderTest() {
SomeObject obj = getSomeObject();
if(obj!=null){
obj.someOtherMethod();
}
return someThing;
}
protected SomeObject getSomeObject() {
return SomeAbstractClass.someMethod();
}
then you can use Mockito Spy to partially mock the object you actually test:
private ClassUnderTest classUnderTest;
#Before
public void setUp() {
classUnderTest= new ClassUnderTest();
classUnderTest = Mockito.spy(classUnderTest);
}
#Test
public void test() {
SomeObject someObject = Mockito.mock(SomeObject.class);
when(classUnderTest.getSomeObject()).thenReturn(someObject);
classUnderTest.methodUnderTest();
verify(someObject).someOtherMethod();
}
#Test
public void testNull() {
when(classUnderTest.getSomeObject()).thenReturn(null);
classUnderTest.methodUnderTest();
verify(something);
}
Use anonymous classes:
public interface SomeObject {
public Object someOtherMethod();
}
public abstract class SomeAbstractClass {
abstract SomeObject someMethod();
}
#Test
public void test() {
SomeAbstractClass target = new SomeAbstractClass() {
SomeObject someMethod() {
// some impl
SomeObject someObject = new SomeObject() {
public Object someOtherMethod() {
// some other impl
}
};
return someObject;
}
};
// now test target
}

Categories