Mock a private method [duplicate] - java

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);
}
}

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);
}
}

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);
}

is there any way in Mockito I set a rule to return a value when a property of a specific object type is called?

I am trying to do the follow (Im sure there is a way, but I cant figure it out).
The problem:
There is a private method in my class, the class was injected using #InjectedMocks.
The private method calls a service and sends as parameter a property from a privated object.
Something like this
private MyObject myObject = new Object();
public void main(){
doSomething();
}
private void doSomething(){
someService(mObject.getValue);
}
The problem is that my object is not that easy and it has an annotation that gives it the value. Seems like with #InjectedMocks the value is never assigned and myObject is always null.
Since both the method and the object are private I cannot just assign the value (And I am avoiding add public setters for them).
My approach:
I want to mock something like this:
when(any(MyObject).class).getValue().thenReturn("something");
So, I will avoid NP at my test.
Is it possible using mockito?
Is there any more elegant way to do this??
I assume that you have some errors in your code example.
The following actually works and prints "foobar": try to compare it with your actual code to see what you forgot.
public class MockitoTest {
#InjectMocks private TestClass test;
#Mock private MyObject mock;
#Test
public void test() {
MockitoAnnotations.initMocks(this);
Mockito.when(mock.getValue()).thenReturn("foobar");
test.main();
}
}
class TestClass {
private MyObject myObject = new MyObject();
public void main() {
doSomething();
}
private void doSomething() {
System.out.println(myObject.getValue());
}
}
class MyObject {
public String getValue() {
return "hello";
}
}
You can mock the object or the method alone using PowerMock.createPartialMock and the proxy the method call.
For example your above code
when(any(MyObject).class).getValue().thenReturn("something");
should be
when(mockedObject).methodCall().thenReturn("something");

Junit test cases fail for abstract method

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);
}
}

Enum Switch to handle interface method calls..bad practice?

I asked this question but I thought maybe this should be a separate question. Given the following class. Is this the best way to handle interface specific method calls based on a enum type? Thanks
#Component
public class HelloWorldImpl implements HelloWorld {
private enum MyEnum{
WALK,RUN,JOG,SKIP
}
#Autowired
#Qualifier("walkService")
private ActivityService walkService;
#Autowired
#Qualifier("runService")
private ActivityService runService;
#Override
public void executeMe(){
MyEnum myEnum = MyEnum.WALK;
for(MyEnum enum : MyEnum.values()){
switch(enum){
case RUN:
runService.execute();
case WALK :
walkService.execute();
etc....
}
}
}
}
I was trying to determine if there was a way I could just use the interface (i.e. ActivityService) to call the execute method instead of being specific to the "MODE" (i.e. switch / if). I was just thinking about what happens if I add a new "MODE" I will have to remember to add a section to this switch statement. Any help is greatly appreciated.
*Update
This exact pattern is suggested here.
I doubt you can make it any better. Well, you could by using the Factory pattern, but that seems to be overkill here.
Take a look at : http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Calendar.java#Calendar.getInstance%28java.util.Locale%29
They use If statements in there. Seems like your code goes one better.
In order to evolve code in a factory scenario :
a) Caller has to know something about the "kind" of concrete implementation needed
b) For each "kind" of service a subclass is needed
Perhaps the only thing to criticize in your implementation is that the "kind" is hidden by a HelloWorldImpl that "knows" which service to return. Its probably more explicit to use subclasses directly because the method "executeMe" says nothing about what kind of service will be chosen at runtime (it depends on the enum).
You'd better add a method to the enum itself:
private enum MyEnum {
WALK {
#Override
public void execute() {
...
}
},
RUN {
#Override
public void execute() {
...
}
}
public abstract void execute();
}
That way, there(s no way you can add a new enum value without implementing its associated execute() method.
And the method becomes:
public void executeMe(){
MyEnum myEnum = MyEnum.WALK;
myEnum.execute();
}
You don't need such switch statement :)
#Override
public void executeMe(){
runService.execute();
}
All you need to is just call method on the interface. And JVM will run whichever implementation is already assigned to your service variable. That is the beauty of interfaces and exact reason they exist for.
Define a mapping of enumKey => concreteActivityServiceBean;
something like this in your spring app context:
<util:map id="activityServiceMapping" key-type="java.lang.String" value-type="com.somePackage.ActivityService" map-class="java.util.HashMap">
<entry key="RUN" value-ref="runServiceImpl" />
<entry key="WALK" value-ref="walkServiceImpl" />
</util:map>
#Component("runServiceImpl")
class RunServiceImpl implements ActivityService {
#Override
public void execute(){ ... }
}
#Component("walkServiceImpl")
class WalkServiceImpl implements ActivityService {
#Override
public void execute(){ ... }
}
And conditionally select the implementation to execute:
#Component
class HelloWorldImpl implements HelloWorld {
#Resource(name = "activityServiceMapping")
private Map<String, ActivityService> activityServices;
#Override
public void executeMe() {
ActivityService activityService = activityServices.get("WALK"); // or "RUN" or use the ENUM values....
activityService.execute();
}
}
I think you should try to refactor your class, so you only need one instance of the ActivityService class. Your code would then look something like this:
#Component
public class HelloWorldImpl implements HelloWorld {
private enum MyEnum{
WALK,RUN,JOG,SKIP
}
#Autowired
private ActivityService activityService;
#Override
public void executeMe(){
MyEnum myEnum = MyEnum.WALK;
activityService.execute(myEnum);
}
}
But it is hard to say whether this is a viable option, without knowing more about the responsibilities of ActivityService.
Or if you really just want the runner class to execute on the correct type every time without using DI or any class selection code or ifs or switch, then ensure that the correct class is instantiated prior to executing it.
ActionExecutor actionExecutor = (ActionExecutor)Class.forName("com.package.name." + action.name()).newInstance();
actionExecutor.execute();
Voila! Problem solved as long as you have a class for every possible action and those classes have a default constructor.
I had faced a similar problem. I found a solution that is more generic that the accepted answer.
The first step is to create an Interface.
public interface ActivityExecutor {
public void execute();
}
Now, all the required classes to execute must implement this class
public class WalkExecutor implements ActivityExecutor {
#Autowired
private WalkService walkService;
public void execute(){
walkService.execute();
}
}
public class RunExecutor implements ActivityExecutor {
#Autowired
private RunService runService;
public void execute(){
runService.execute();
}
}
Now the enums are declared in the following way
private enum MyEnum {
WALK {
#Override
public String getClassName() {
return "com.basepackage.WalkExecutor";
}
},
RUN {
#Override
public String getClassName() {
return "com.basepackage.RunExecutor";
}
}
public abstract String getClassName();
}
In the processing part, do the following.
String className = MyEnum.WALK.getClassName();
Class<?> clazz = Class.forName(className);
private static ApplicationContext appContext;
ActivityExecutor activityExecutor = (ActivityExecutor) appContext.getBean(clazz);
activityExecutor.execute(); // executes the required Service
Another way of fixing this problem could be:
public enum ExecutorType {
WALK, RUN
}
interface Executor {
void execute();
ExecutorType type();
}
Here we are able to do DI and create CDI/Spring Bean
final class WalkExecutor implements Executor {
#Override
public void execute() {
/** some logic **/
}
#Override
public ExecutorType type() {
return ExecutorType.WALK;
}
}
then we can access valid executor for given type.
public final class ExecutorService {
private final Map<ExecutorType, Executor> executorMap;
ExecutorService(List<Executor> executors) {
this.executorMap = executors.stream().collect(Collectors.toMap(Executor::type), Function.identity()));
}
public void execute(ExecutorType type) {
executorMap.get(type).execute();
}
}
Additionally we can ensure that every Executor type is implemented using either integration test or configuration class.
Configuration class using Spring:
#Configuration
class ExecutorConfiguration {
/** other beans definition **/
#Bean
ExecutorService executorService(List<Executor> executors) {
if (!allExecutorsImplemented(executors)) {
throw new RuntimeException("Invalid executor configuration");
}
return new ExecutorService(executors);
}
private boolean allExecutorsImplemented(List<Executor> executors) {
return executors.stream().map(Executor::type).distinct().count() == ExecutorType.values().length;
}
}

Categories

Resources