Testing a Function using Mock - junit

I want to test a function which has a call to another function inside it(which accepts two parameters)
I want to mock that inside function.But I am having difficulty in what to pass as a parameter
void func(classA a,classB b)
{
List<ClassC> list= Objd.func2(a.getSome(),b)
///some other things
}
now I want to mock this func2 , I already have an interface for class of obj C.
I tried using
InterfaceClassD objD=Mockito.mock(InterfaceClassD.class)
Mockito.when(obj.func2(a.getsome(),b)).thenreturn(null);
but it doesn't work,the func2 executes
I even tried
InterfaceClassD objD=Mockito.mock(InterfaceClassD.class)
Mockito.when(obj.func2(anyList(),any(classB.class)).thenreturn(null);
NOTE - a.getSome() returns list
but it too doesn't work,the func2 executes

It's hard to answer this question without more context.
In the function "func", where does the reference to "Objd" come from? Where is it declared?
There are two steps in creating and using mocks in a test:
creating the mock
injecting the mock
"Injecting the mock" refers to (somehow) replacing the reference to the real object that the function will use with the mock version you've created with Mockito.
Example:
// Class under test
public class Foo {
// this is the object we need to mock
private InterfaceClassD objD;
void func(classA a,classB b) {
// here is where we use "objD"
List<ClassC> list= objD.func2(a.getSome(),b)
///some other things
}
}
In order to write a test with a mock objD you have to replace the "real" objD with the mock just before you invoke the method (function) being tested.
Typically it is done with either constructor injection, setter injection, or Mockito annotations.
Example with constructor injection:
// Class under test
public class Foo {
// this is the object we need to mock
private InterfaceClassD objD;
// constructor injection
public Foo(InterfaceClassD objD) {
this.objD = objD;
}
void func(classA a,classB b) {
// here is where we use "objD"
List<ClassC> list= objD.func2(a.getSome(),b);
///some other things
}
}
// Unit test
public class FooTest {
#Test
public void someTest() {
// create the mock:
InterfaceClassD mock = Mockito.mock(InterfaceClassD.class);
// inject the mock:
Foo foo = new Foo(objD);
// test: this should call method func but use the mock
foo.func(dummyA, dummyB);
// verify/assert something...
}
}
Example using setter injection:
// Class under test
public class Foo {
// this is the object we need to mock
private InterfaceClassD objD;
// setter injection
public void setInterfaceClassD(InterfaceClassD objD) {
this.objD = objD;
}
void func(classA a,classB b) {
// here is where we use "objD"
List<ClassC> list= objD.func2(a.getSome(),b);
///some other things
}
}
// Unit test
public class FooTest {
#Test
public void someTest() {
// create the mock:
InterfaceClassD mock = Mockito.mock(InterfaceClassD.class);
Foo foo = new Foo();
// inject the mock:
foo.setInterfaceClassD(mock);
// test: this should call method func but use the mock
foo.func(dummyA, dummyB);
// verify/assert something...
}
}
Example using Mockito annotations and JUnit 5:
// Class under test
public class Foo {
// this is the object we need to mock
private InterfaceClassD objD;
void func(classA a,classB b) {
// here is where we use "objD"
List<ClassC> list= objD.func2(a.getSome(),b);
///some other things
}
}
// Unit test
// Note the Mockito extension annotation.
#ExtendWith(MockitoExtension.class)
public class FooTest {
// the Mockito JUnit extension will instantiate this automagically.
// The name of the mock must exactly match the name of the field in
// containing class.
private #Mock InterfaceClassD objD;
// Mockito annotation processing will create an instance of Foo, and
// replace any of its fields with any mocks that have the same name
// and type. In this case, objD.
private #InjectMocks Foo foo;
#Test
public void someTest() {
// Just use it.
// test: this should call method func but use the mock
foo.func(dummyA, dummyB);
// verify/assert something...
}
}

Related

Mockito using what "When ... thenReturn" returns caused NullPointerException

I have a third party class called Person, one method is to return a string:
public class Person<T> {
public String getName(Object<T> obj) {
// some code here
return "some string"
}
And another third party class called SomeClass, one method is to return a Person object:
public class SomeClass {
public <T> Person<T> createPerson(Object obj) {
// some code here
return new Person<T>(....)
}
}
My class that uses the above two classes to create a person first, then get person's name. I can't make changes to MyClass because it has been system tested successfully:
public class MyClass {
public String myMethod() {
Person<T> person = someClass.createPerson(obj);
return person.getName(...);
// NullPointerException when junit because "person" object is null
}
}
Now I am working on junit to test MyClass to satisfy the code coverage requirements. For some reason, it always gave me NullPointer exception when person.getName() is called by junit.
public class MyClassTest {
#MockBean
private SomeClass someClass;
#Autowired
private MyClass myClass;
#Test
public void test(){
Person<Student> studentPerson =
(Person<Student>)Mockito.mock(Person.class);
Mockito.when(someClass.createPerson(ArgumentMatchers.any()))
.thenReturn(studentPerson);
Mockito.when(studentPerson.getName(ArgumentMatchers.any()))
.thenReturn("some data");
// call real method
myClass.myMethod(); // failed with NullPointerException
I am not sure why studentPerson is not mocked correctly which caused a NullPointerException becacuse it's Null. Can someone please help? Thanks.

JUnit mocking method call

I am writing a Junit test for a method 'methodA' which is in class 'classA'. In 'methodA' another method 'methodB' of class 'classB' is called. The 'methodB' calls soap web-service. I want to mock this methodB soap web-service call. In this case i am calling classA.methodA. Here i don't find a way that at the time when classB.methodB is called then mock value should get updated. I went through many links about Mockito, but they all refer on updating the mock value from junit class only. So, how can i pass mocked value their.
#Test
public void junitTest() {
String arg1 = "arg1";
classA aObj = new classA();
aObj.methodA(arg1);
}
public classA {
public string methodA(String arg1) {
classB bObj = new classB();
bObj.methodB();
//somwthing on arg1
return result;
}
}
public classB {
public list methodB() {
//web-service call
return list from web - service.
}
}
I am writing a Junit test for a method methodA which is in class
classA
Since you are unit testing methodA of classA, you should be focusing on mocking just the bObj.methodB(); call. You should not get into what it does or doesn't internally.
Not you are creating classB object in methodA which is not the ideal scenario. You should make bObj as the instance variable of classA with appropriate getter, setters and constructor.
Then from you testing class set this classB dependency.
You should structure your code and something tests like this:
class classAMicroTest {
#Test
public void junitTest() {
String arg1 = "arg1";
classA aObj = new classA();
classB mockedBobj = Mockito.mock(classB.class);
Mockito.when(mockedBobj.methodB()).thenReturn(new ArrayList<>());
aObj.setbObj(mockedBobj);
aObj.methodA(arg1);
Mockito.verify(mockedBobj, times(1)).methodB());
}
}
class classA {
classB bObj;
public void setbObj(classB bObj) {
this.bObj = bObj;
}
public String methodA(String arg1) {
bObj.methodB();
// somwthing on arg1
return result;
}
}
class classB {
public List<String> methodB() {
return new ArrayList<>();
}
}

Unit test WCMUsePOJO class

I am writing unit test cases for following class which extends WCMUsePOJO. Now, this class is using a getSlingScriptHelper method shown below.
public class ConstantsServiceProvider extends WCMUsePojo {
private static final Logger logger = LoggerFactory.getLogger(ConstantsServiceProvider.class);
private String var1;
#Override
public void activate() throws Exception {
ConstantsService constantsService = getSlingScriptHelper().getService(ConstantsService.class);
if(constantsService != null) {
var1 = constantsService.getVar1();
}
}
public string getVar1() { return var1; }
}
The question is how do I mock getSlingScriptHelper method? Following is my unit test code.
public class ConstantsServiceProviderTest {
#Rule
public final SlingContext context = new SlingContext(ResourceResolverType.JCR_MOCK);
#Mock
public SlingScriptHelper scriptHelper;
public ConstantsServiceProviderTest() throws Exception {
}
#Before
public void setUp() throws Exception {
ConstantsService service = new ConstantsService();
scriptHelper = context.slingScriptHelper();
provider = new ConstantsServiceProvider();
provider.activate();
}
#Test
public void testGetvar1() throws Exception {
String testvar1 = "";
String var1 = provider.getVar1();
assertEquals(testvar1, var1);
}
}
The only thing that you should "have to"* mock is the SlingScriptHelper instance itself, so that it will mimic the dependency injection of the declared service.
Everything else (e.g. the Bindings instance) can be a concrete implementation, for example:
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.junit.Test;
import javax.script.Bindings;
import javax.script.SimpleBindings;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ConstantsServiceProviderTest {
private SlingScriptHelper mockSling = mock(SlingScriptHelper.class);
private ConstantsServiceProvider constantsServiceProvider = new ConstantsServiceProvider();
private Bindings bindings = new SimpleBindings();
#Test
public void testFoo() throws Exception {
//Arrange
final String expected = "Hello world";
final ConstantsService testConstantsService = new TestConstantsService(expected);
when(mockSling.getService(ConstantsService.class)).thenReturn(testConstantsService);
bindings.put(SlingBindings.SLING, mockSling);
//Act
constantsServiceProvider.init(bindings);
//Assert
final String actual = constantsServiceProvider.getVar1();
assertThat(actual, is(equalTo(expected)));
}
class TestConstantsService extends ConstantsService {
String var1 = "";
TestConstantsService(String var1) {
this.var1 = var1;
}
#Override
String getVar1() {
return var1;
}
}
}
The entry point here, as you said above, is via the init() method of the WCMUsePojo superclass (as this method is an implementation of the Use.class interface, this test structure also works for testing that via that interface, even if you don't use WCMUsePojo directly.)
*this could be any type of test-double, not necessarily a mock.
You shouldn't create a mock for ConstantsServiceProvider.class if you want to unit-test it. Instead, you should create mocks of its internal objects. So:
Create real instance of ConstantsServiceProvider with new
Mock objects that are returned by getSlingScriptHelper().getService(.) methods. Usually, dependencies are provided (injected) to classes by some container like Spring or simply provided by other classes of your app using setters. In both cases mocks creation is easy.
If your current implementation doesn't allow this - consider refactoring.
You are testing void activate() method which doesn't return anything. So, you should verify calling constantsService.getVar1() method.
I strongly advice you to study Vogella unit-testing tutorial
Here one of possible solution.
The main idea is to have a real object of your class but with overridden getSlingScriptHelper() to return mocked scriptHelper.
I mocked the ConstantsService as well but may be not needed, I don't know your code.
public class ConstantsServiceProviderTest {
#Mock
public SlingScriptHelper scriptHelper;
#Test
public void getVar1ReturnsActivatedValue() throws Exception {
// setup
final String expectedResult = "some value";
// Have a mocked ConstantsService, but if possible have a real instance.
final ConstantsService mockedConstantsService =
Mockito.mock(ConstantsService.class);
Mockito.when(
mockedConstantsService.getVar1())
.thenReturn(expectedResult);
Mockito.when(
scriptHelper.getService(ConstantsService.class))
.thenReturn(mockedConstantsService);
// Have a real instance of your class under testing but with overridden getSlingScriptHelper()
final ConstantsServiceProvider providerWithMockedHelper =
new ConstantsServiceProvider() {
#Override
SlingScriptHelper getSlingScriptHelper() {
return scriptHelper;
}
};
// when
String actualResult = providerWithMockedHelper.getVar1();
// then
assertEquals(expectedResult, actualResult);
}
}

JUNIT test case for void method

I have a method whose JUnit test case I have to write. It just calls the main processing method of the project and does nothing else. Also, the main processing method also has return type as void.
How shall I test such a "method1"?
public void method1() {
obj1.mainProcessingMethod():
}
Given a class:
public class A {
private Obj obj1;
public void method1() {
obj1.mainProcessingMethod();
}
public void setObj1(Obj obj1) {
this.obj1 = obj1;
}
}
In test for this class, the only thing to test would be verification whether method obj1.mainProcessingMethod() was invoked exactly once.
You can achieve this with Mockito.
import org.junit.Test;
import org.mockito.Mockito;
public class ATest {
private Obj obj1 = Mockito.mock(Obj.class);
private A a = new A();
#Test
public void testMethod1() {
a.setObj1(obj1);
a.method1();
Mockito.verify(obj1).mainProcessingMethod();
}
}
Here you create a mock object for class Obj, inject it into instance of A, and later use mock object to check which method invocations it recorded.
Inside the test you need to verify that the method mainProcessingMethod(): is called on the object obj1.
you can use something like
Mockito.verify(yourMockObject);

JMockit mock protected method in superclass and still test method in real child class

I am still learning JMockit and need help understanding it.
I am testing a class that uses superclass methods. My test gets a null pointer when it attempts to use the superclass method due to code inside it that uses struts action context to get the session and pull an object from the session.
The method I want to bypass the struts session stuff inside the protected method.
public class MyExtendingClass extends MySuperClass{
public void methodIamTesting(){///}
}
public abstract class MySuperClass{
//I want to mock this method
protected Object myProtectedSuperClassMethod(){
// struts action context code that returns an object//}
}
Test code
#Test
public void testRunsAndDoesntPass() {
Mockit.setUpMock(MySuperClass.class, new MySuperClass(){
public Object myProtectedSuperClassMethod() {
return object;
}
});
// real class method invocation happens
assertEquals(expected, actual);
}
I keep getting NullPointers just like if I didn't have the mock
Not sure what to try next. All the docs and code samples I have read say to just declare the superclass method as public in the setUpMock and it should work.
I can't mock the entire class because that is the class I am testing.
I discovered that I needed to create the MockClass then reference it using setupmock correctly.
I am really falling in love with JMockit.
#MockClass(realClass = MyExtendingClass.class)
public static class MockSuperClass {
final Object object = new Object();
#Mock
public Object myProtectedSuperClassMethod() {
return object;
}}
#Test
public void testRunsAndNowWillPass() {
Mockit.setUpMock(MySuperClass.class, new MockSuperClass(){
public Object myProtectedSuperClassMethod() {
return object;
}});
// real class method invocation happens where i set expected and actual
assertEquals(expected, actual);
}
you mask the parent class implementation out totally #Mocked final MySuperClass base
abstract class MySuperClass{
protected Object myProtectedSuperClassMethod(){
}
class MyExtendingClass extends MySuperClass{
public void methodIamTesting(){///}
}
#Test
public void testRunsAndDoesntPass(#Mocked final MySuperClass base ) {
//you could mask out all the base class implementation like this
new Expectations(){{
invoke(base, "myProtectedSuperClassMethod");
}};
// real class method invocation happens
// ...
assertEquals(expected, actual);
}