Junit test cases fail for abstract method - java

I have an abstract method checkStatus() which has implementations in Checker.java class. But when I execute the Junit test case on abstract class method validate() that in-turn calls checkStatus(), fails due to missing spring dependency in Checker.java class.
Details provided below.
Abstract class:
public abstract class MyAbstractClass
{
protected abstract boolean checkStatus();
public boolean validate()
{
//Some code
return checkStatus();
}
}
Implementation class:
public class Checker extends MyAbstractClass
{
#Autowired
private StatusHelper helper;
public void setHelper(StatusHelper helper){
this.helper = helper;
}
#Override
public boolean checkStatus() throws Exception{
if(null == helper){
throw new Exception("Helper is null");
}
return helper.validateStatus();
}
}
JUnit test:
class AbstractClassTest
{
MyAbstractClass absClass = Mockito.mock(Checker.class, Mockito.CALLS_REAL_METHODS);
#Test
public void testStatusOfChecker()throws Exception {
boolean status = absClass.validate();
assertEquals(status, true);
}
}
I believe I can inject the helper object manually like the following
Checker check = mock(Checker.class);
StatusHelper helper = mock(StatusHelper.class);
check.setHelper(helper);
but the problem here is, I cannot inject directly to absClass object as the setHelper() is not inherited.
I can instead write test case directly to subclass, but I needed this way to test some other functionality in validate() method of abstract class.
Can someone help me how to set helper object to the sub class or is there different way to do it in Junit? Any help or links that contain relevant info is highly appreciable.
Thanks,

The only way to test an abstract class is by testing an implementation (which could be an anonymous class).
public class AbstractClassTest {
#Test
public void testStatusOfChecker() throws Exception {
MyAbstractClass object = new MyAbstractClass() {
protected boolean checkStatus() {
return true; //this is the place to provide the expected value
}
}
boolean status = absClass.validate();
assertEquals(status, true);
}
}
If you want to test the Checker implementation then you must not mock it.
public class CheckerTest {
#Test
public void test() {
StatusHelper helper = mock(StatusHelper.class);
Checker checker = new Checker();
checker.setHelper(helper);
when(helper.validate()).thenReturn(true);
boolean status = checker.validate();
assertEquals(status, true);
}
}
By the way I strongly recommend to use constructor injection (see Why field injection is evil). The test would then look like this
public class CheckerTest {
#Test
public void test() {
StatusHelper helper = mock(StatusHelper.class);
Checker checker = new Checker(helper);
when(helper.validate()).thenReturn(true);
boolean status = checker.validate();
assertEquals(status, true);
}
}

Related

Skip null check in mockito

I am trying to write unit test cases for one of the methods in code.Below is the method
public boolean isValid() {
if(object == null)
return false
//do something here and return value.
}
The object is created by this method which is done before without getter setter method.
private Object returnObject() {
object = Axis2ConfigurationContextFactory.getConfigurationContext();
return object;
}
When I try to test isValid(), the object is always null, so it never goes in the code to do something.
I was checking if there is any way to skip that line or make the object not null. I also tried creating an object using returnObject method. But it uses Axis library classes which throws error if it does not find certain data. What can be done in this case? I am dealing with legacy code so any pointers would be helpful.
Edit : Adding test implementation.
#PowerMockIgnore({ "javax.xml.*", "org.w3c.dom.*", "javax.management.*" })
public class ClassTest {
private ClassTest classTestObj;
#BeforeMethod
public void callClassConstructor() {
classTestObj = //call class constructor
}
#BeforeClass
public void setUpClass() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public boolean isValidTest() {
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}
As I mentioned in the before comment, you can make use of MockedStatic to mock the static method - https://javadoc.io/static/org.mockito/mockito-core/4.4.0/org/mockito/Mockito.html#static_mocks
So your code will somewhat look like the below one if you are making use of Mockito instead of PowerMockito.
#RunWith(MockitoJUnitRunner.class)
public class ClassTest
{
#Mock
private Object mockAxis2ConfigurationContextFactoryObject;
#Test
public boolean isValidTest() {
try (MockedStatic<Axis2ConfigurationContextFactory> mockedStatic = mockStatic(Axis2ConfigurationContextFactory.class)) {
mockedStatic.when(()->Axis2ConfigurationContextFactory.getConfigurationContext()).thenReturn(mockAxis2ConfigurationContextFactoryObject);
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}

Intercepting real non-static method calls with Mockito

Is there any way, using Mockito or PowerMockito, to intercept calls to non-static methods of an object, or at least of a singleton object?
An example is provided by the following classes:
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton(Object parameter) {}
public static Singleton getInstance(Object parameter) {
if (INSTANCE == null) {
INSTANCE = new Singleton(parameter);
}
return INSTANCE;
}
public String process(String a, String b) {
return (a + b);
}
// Other methods
}
public class Foreign {
private Foreign() {}
public static void main(String[] args) {
System.out.println(Singleton.getInstance(new Object()).process("alpha", "beta"));
}
}
The Singleton object is created in a Foreign class, outside the control of some test code (not shown above). Neither of these two classes can be modified. The objective is to intercept calls to the non-static process() method in the test code so that, for certain values, a different result is returned, e.g. the call
Singleton.getInstance(new Object()).process("alpha", "beta");
mocked to return "alpha-beta" instead of the expected "alphabeta".
One solution could be intercepting the Singleton.getInstance() method to instantiate a custom subclass of the Singleton, e.g. using
public class SubSingleton extends Singleton {
public SubSingleton(Object parameter) {
super(parameter);
}
public String process(String a, String b) {
if ("alpha".equals(a) && "beta".equals(b)) {
return a + "-" + b;
}
return super.process(a + b);
}
}
Then, calls to the Singleton.process() method would be intercepted as in:
Object parameter = new Object();
PowerMockito.doReturn(new SubSingleton(parameter)).when(Singleton.class, "getInstance", parameter);
However, the Singleton class above only provides a private constructor, so it cannot be extended. Using PowerMockito.whenNew() to return a partial mock (spy) will also not work, since the Singleton class does not provide a no-args constructor.
Can the desired mocking be implemented in any other way? Can it be done for non-singleton classes?
Firstly, you can use whenNew for objects with constructor with some params:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Mock
Singleton singletonMock;
#Before
public void setUp() throws Exception {
PowerMockito.whenNew(Singleton.class)
.withAnyArguments()
.thenReturn(singletonMock);
}
#Test
public void testMockNew() throws Exception {
Mockito.when(singletonMock.process(anyString(), anyString())).thenReturn("sasa");
Foreign.main(new String[0]);
}
}
Secondly, why not stub getInstance instead of new:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Test
public void testMockNew() {
PowerMockito.mockStatic(Singleton.class);
Singleton singletonMock = Mockito.mock(Singleton.class);
PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
Mockito.when(singletonMock.process(anyString(), anyString())).thenReturn("sasa");
Foreign.main(new String[0]);
}
}
Thirdly, to intercept the process method:
create real singleton
create a mock singleton
mock static getInstance to return the mock. NOTE: you must call mockStatic after getting real instance.
use thenAnswer to check the arguments on process call
return desired answer if they match desired pattern
else call real method on real singleton
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Test
public void testMockNew() {
var singletonReal = Singleton.getInstance(new Object());
var singletonMock = Mockito.mock(Singleton.class);
PowerMockito.mockStatic(Singleton.class);
PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
Mockito.when(singletonMock.process(anyString(), anyString())).thenAnswer((args) -> {
String a = args.getArgument(0);
String b = args.getArgument(1);
if ("alpha".equals(a) && "beta".equals(b)) {
return "sasa";
} else {
return singletonReal.process(a, b);
}
});
Foreign.main(new String[0]);
}
}
And finally, use a spy instead of a mock
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class SingletonPrivateNewTest {
#Test
public void testMockNew() {
var singletonReal = Singleton.getInstance(new Object());
var singletonMock = Mockito.spy(singletonReal);
PowerMockito.mockStatic(Singleton.class);
PowerMockito.when(Singleton.getInstance(any())).thenReturn(singletonMock);
Mockito.when(singletonMock.process("alpha", "beta")).thenReturn("sasa");
// NOTE: real method is called for other args
Foreign.main(new String[0]);
}
}

Mock a private method [duplicate]

This question already has answers here:
How to mock private method for testing using PowerMock?
(6 answers)
Closed 5 years ago.
I have a method which is private . Now, I do not want to call this private method while doing unit test on execute() method. I have tried with PowerMockito and all, but with all type of mockings it still enter into the private method.
Please suggest with workable testcase. Would appreciate the same.
#Component
public class Employee implements SuperClass {
#Autowired
private FileTraverse fileTraverse;
#Override
public void execute() throws Exception {
List<String> traverse = fileTraverse.getFiles();
Boolean t = isFileTraversed(traverse);
}
private Boolean isFileTraversed(List<String> param1) {
Boolean flag;
//do some DB operation and return flag;
}
}
#glytching is right. The best variant it's to extract method in a new service/component and create mock for one. In this case, your code is testable, you can re-use this component ...
BUT in case if you have only one use case for this method and you don't want to create a service/component just for one method, helper method, you can change the method visibility level from private to protected or package-default. In this case, you can override this method in subclass for testing and work with this sub-class. What you should do :
create a subclass for the class that you want to test and use the instance of this subclass instead of the target class.
--service that you have and need to test one
public class MainService {
#Autowired
private SecondService secondService;
public Object getResultFromMainService(){
return getResultFromMainServiceFromPrivate();
}
--here I changed 'private' into 'default-package'
Object getResultFromMainServiceFromPrivate(){
return secondService.getResult();
}
}
_
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = ServiceOverrideTestConfiguration.class)
public class MainServiceTest {
#Autowired
#Qualifier("subMainService") // or add #Primary and don't use Qualifier
private MainService service;
#Autowired
private SecondService secondService;
#Test
public void test(){
Object result = service.getResultFromMainService();
--here, method getResultFromMainService call inside the overrided
method that we can change
assertNotNull(result);
}
}
#ContextConfiguration
#Import(ApplicationConfigure.class)
class ServiceOverrideTestConfiguration {
#Bean("subMainService")
// or add #Primary and don't use Qualifier
MainService mainServiceSubBean(){
return new MainServiceUnderTest();
}
}
class MainServiceUnderTest extends MainService{
#Override
Object getResultFromMainServiceFromPrivate(){
return "SOME DEFAULT";
}
}
! Pls, consider this approach only as a workaround in rare cases when you need to mock/stub some method and you can't use PowerMock or any other libs. Better, try to do refactoring and bring testability in your code
Don't mock private methods.
See the suggestion below:
#Component
public class Employee implements SuperClass {
#Autowired
private FileTraverse fileTraverse;
#Override
public void execute() throws Exception {
List<String> traverse = fileTraverse.getFiles();
Boolean t = isFileTraversed(traverse);
}
private Boolean isFileTraversed(List<String> param1) {
Boolean flag;
//do some DB operation and return flag;
}
}
So inside isFileTraversed - you will have a DB operation. This operation will probably be executed through a DAO/Repository object.
So your code will probably look like:
#Component
public class Employee implements SuperClass {
#Autowired
private FileTraverse fileTraverse;
#Autowired
private DatabaseAccessDao dbAccess;
#Override
public void execute() throws Exception {
List<String> traverse = fileTraverse.getFiles();
Boolean t = isFileTraversed(traverse);
}
#Override
private Boolean isFileTraversed(List<String> param1) {
Boolean flag;
flag = dbAccess.checkFileTraversed(param1);
return flag;
}
}
What you need to do is to mock the public checkFileTraversed() method on the DatabaseAccessDao class.
1) Don't #Autowire on fields - prefer constructor injection.
2) Are you sure you want to return a Boolean? Is "null" allowed as a return value? If not - consider using the primitive boolean type;
Everybody else is right. You should try to avoid mocking private methods as much as you can. And if you really need to mock it, just drop the private to put it in default scope.
BUT
For the sake of completeness, you can indeed to it with PowerMock. Here is an example using PowerMock and EasyMock.
public class Employee {
public void execute() {
// If our mock is working, isFileTraversed will return false
assertThat(isFileTraversed(Collections.emptyList())).isFalse();
}
private Boolean isFileTraversed(List<String> param1) {
return true;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(Employee.class)
public class EmployeeTest {
#Test
public void execute() throws Exception {
Employee employee = PowerMock.createPartialMockForAllMethodsExcept(Employee.class, "execute");
PowerMock.expectPrivate(employee, "isFileTraversed", Collections.emptyList()).andReturn(false);
PowerMock.replay(employee);
employee.execute();
PowerMock.verify(employee);
}
}

How to Mock Object in Jmock? If Object created using new operator

I have below piece of code in method.
AdminServiceProxy proxy=new AdminServiceProxy();
boolean flag=proxy.isAdminFree();
How to mock "AdminServiceProxy " using Jmock. Since object is getting created using new operator.
You can't.
One possible solution is to create an AdminServiceProxyFactory interface and implementation:
public interface AdminServiceProxyFactory {
public AdminServiceProxy createAdminServiceProxy();
}
public class AdminServiceProxyFactoryImpl {
public AdminServiceProxy createAdminServiceProxy() {
return new AdminServiceProxy();
}
}
Then in your class add a setter and private attribute:
public class Foo {
private AdminServiceProxyFactory adminServiceProxyFactory;
...
public void setAdminServiceProxyFactory(AdminServiceProxyFactory factory) {
adminServiceProxyFactory = factory;
}
public myMethod() {
...
AdminServiceProxy proxy=adminServiceProxyFactory.createAdminServiceProxy();
boolean flag=proxy.isAdminFree();
...
}
}
Now you can create a mock AdminServiceProxyFactory and inject it into your class. You then tell your mock factory to return a mock AdminServiceProxy when it is called.
jMock does not support the mocking of "future objects" or the mocking of constructors.
Other mocking libraries provide such support. One of them (which I developed) is JMockit, whose syntax was originally inspired by jMock's "Expectations". In this case, we could have:
#Test
public void exampleTestThatMocksAFutureObject(#Mocked AdminServiceProxy proxy) {
new Expectations() {{ proxy.isAdminFree(); result = true; }};
// Call code under test which instantiates an AdminServiceProxy...
boolean adminFree = new AdminServiceProxy().isAdminFree();
assertTrue(adminFree);
}

Mock inherited method in Mockito Java

My class structure is as follows:
public class MyParentClass {
void doSomethingParent() {
System.out.println("something in parent");
}
}
public class MyClass extends MyParentClass {
protected String createDummyRequest(Holder myHolder) {
//...
super.doSomethingParent();//I want to avoid this
//...
callingDB();
return "processedOutput";
}
private void callingDB() {
System.out.println("Calling to DB");
}
}
Then my unit test:
public class UnitTest {
public void testCreateDummyRequest() {
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.mock(MyClass.class);
//mock doSomethingParent()
//mock callingDB()
//as mockObj is a fully mock, but I need to run my real method
//Mockito.when(mockObj.createDummyRequest(mockHolder)).thenCallRealMethod();
mockObj.createDummyRequest(mockHolder);
//Problem: doSomethingParent() is getting called though I have mocked it
}
}
How do I prevent the calling of the super.doSomethingParent() in my method? (method which I am writing my test)
With this class structure mocking and testing is real hard. If possible, I'd advice to change the structure as in mist cases a class structure that's hard to mock and test is equally hard to extend and maintain.
So if you could change your class structure to something similar to:
public class MyClass {
private DoSomethingProvider doSomethingProvider;
private DbConnector dbConnector;
public MyClass (DoSomethingProvider p, DbConnector c) {
doSomethingProvicer = p;
dbConnector = c;
}
protected String createDummyRequest(Holder myHolder){
//...
doSomethingProvider.doSomethingParent();
//...
dbConnector.callingDB();
return "processedOutput";
}
}
Then you could easily create your instance with mocks of DoSomethingProvider and DbConnector and voila....
If you can't change your class structure you need to use Mockito.spy instead of Mockito.mock to stub specific method calls but use the real object.
public void testCreateDummyRequest(){
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.spy(new MyClass());
Mockito.doNothing().when(mockObj).doSomething();
mockObj.createDummyRequest(mockHolder);
}
Note: Using the super keyword prevents Mockito from stubbing that method call. I don't know if there is a way to stub calls to super. If possible (as in you didn't override the parent method in your class), just ommit the keyword.
I faced similar issue, so I find out that using spy() can hepld.
public class UnitTest {
private MyClass myObj;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
myObj= spy(new MyClass());
}
#Test
public void mockedSuperClassMethod(){
doNothing().when((MyParentClass )myObj).doSomethingParent();
//...
}
}
This approach works for me.
I found another approach, which turned out to be very useful in my case.
In the case I had, I needed to create a new class extending another, which included a very complex (legacy code) protected final method. Due to the complexity, it wasn't really possible to refactor to use composition, so here's what I came up with.
Let's say I have the following:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
class MyNewClass extends Parent {
#Override
public void implementMe() {
// custom stuff
doComplexStuff(/* a long parameter list */); // calling the parent
// some more custom stuff
}
}
Here's how I rearranged this code:
abstract class Parent {
public abstract void implementMe();
protected final void doComplexStuff( /* a long parameter list */) {
// very complex legacy logic
}
}
interface ComplexStuffExecutor {
void executeComplexStuff(/* a long parameter list, matching the one from doComplexStuff */);
}
class MyNewClass extends Parent {
private final ComplexStuffExecutor complexStuffExecutor;
MyNewClass() {
this.complexStuffExecutor = this::doComplexStuff;
}
MyNewClass(ComplexStuffExecutor complexStuffExecutor) {
this.complexStuffExecutor = complexStuffExecutor;
}
#Override
public void implementMe() {
// custom stuff
complexStuffExecutor.doComplexStuff(/* a long parameter list */); // either calling the parent or the injected ComplexStuffExecutor
// some more custom stuff
}
}
When creating instance of MyNewClass for "production" purposes, I can use the default constructor.
When writing unit tests, however, I'd use the constructor, where I can inject ComplexStuffExecutor, provide a mock there and only test my custom logic from MyNewClass, i.e.:
class MyNewClassTest {
#Test
void testImplementMe() {
ComplexStuffExecutor complexStuffExecutor = Mockito.mock(ComplexStuffExecutor.class);
doNothing().when(complexStuffExecutor).executeComplexStuff(/* expected parameters */);
MyNewClass systemUnderTest = new MyNewClass(complexStuffExecutor);
// perform tests
}
}
At first glance, it seems like adding some boilerplate code just to make the code testable. However, I can also see it as an indicator of how the code should actually look like. Perhaps one day someone (who would find courage and budget ;) ) could refactor the code e.g. to implement the ComplexStuffExecutor with the logic from doComplexStuff from Parent, inject it into MyNewClass and get rid of inheritance.
Here is how it can be done
public class BaseController {
public void method() {
validate(); // I don't want to run this!
}
}
public class JDrivenController extends BaseController {
public void method(){
super.method()
load(); // I only want to test this!
}
}
#Test
public void testSave() {
JDrivenController spy = Mockito.spy(new JDrivenController());
// Prevent/stub logic in super.method()
Mockito.doNothing().when((BaseController)spy).validate();
// When
spy.method();
// Then
verify(spy).load();
}
Source: https://blog.jdriven.com/2013/05/mock-superclass-method-with-mockito/

Categories

Resources