How to mock a function call in java - java

I am new to Unit testing and trying to figure out the different implementations of testing. I m trying to figure out how to mock a particular function call. I came across Mock Spy but didn't quite understand how it's been used. Can someone tell me how mocking is done in such cases...
Class ABC {
void display(String name, int id){
validateName(name);
validateId(id);
}
}
Class TestIt{
#Test
void testValidation(){
//how to mock validateName function call and test only validateId ?
ABC obj=new ABC();
obj.display("abc",2);
}
}

Some mocking frameworks allow partial mocks (most of the mocked class is actuall the real thing, just some methods are mocked). If your example is anywhere near the real code, I would not test the two methods separately. If one of these methods do something that is not wanted in a test, like accessing an external service (DB, webservice, filesystem), the I would encapsulate that functionality into an adapater class and inject it into ABC. Then you can mock the adapter.

Related

Mocking a dependent class using Mockito in JAVA

I am quite new to Mockito. I apologise if my question sounds sill. I have a standalone JAVA application for which I have to write Unit test cases using JUnit and Mockito. The important thing is that I cannot change the code as it has been written by someone else and Integration testing has been completed. I have tried to search for similar questions, but couldnt find anything. Solutions suggested in somewhat similar questions, didnt work :(
I have attached the flow control diagram.I want to mock the dependent classes. For example when I am Unit testing 'Class 1 --> Method 1', I want to mock the output of 'Method 2 in Class 2' WITHOUT CALLING it. I have tried to use Mockito.when and Mockito.doReturn. Both call the dependent methods.
Can someone please suggest me some ideas to achieve this ?
//Pseudocode of Class 1
public class Class1 {
public boolean method1() {
Class2 c2 = new Class2();
boolean b1 = c2.method2();
}
}
//Pseudocode of Class 2
public class Class2 {
public boolean method2() {
Class3 c3 = new Class3();
boolean b2 = c3.method3();
}
}
... Likewise same for Class 3, 4 and 5
What you're being asked to do is write unit tests for logic which was written by someone who knows absolutely nothing about writing code for test-ability. Probably a developer who's been writing code for a very long time, does things in an "old school" way and thinks he's way too important to write unit tests. Whoever wrote the logic you're testing needs to go back to school and learn some new tricks.
Anyway that doesn't help you, so you can still unit test this logic, it's just more of a pain. Mockito alone can't do it, you need "PowerMockito" which will let you mock the construction of Class2.
First things first you need to add 2 new test dependencies to your project "powermock-api-mockito"+"powermock-module-junit4".
A test class for you case would look something like:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Class1.class)
public class Class1Test {
private Class1 testSubject;
#Mock
private Class2 class2;
#Test
public void testMethod1() throws Exception {
testSubject.method1();
verify(class2).method2();
}
#Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.whenNew(Class2.class).withNoArguments().thenReturn(class2);
testSubject = new Class1();
}
}
So as you can see PowerMockito lets you mock out construction on new Class2 instances by using PowerMockito.whenNew(), this will only work if you've "prepared" Class1 using the annotation #PrepareForTest(Class1.class) otherwise Class1 can't be injected with the mock Class2 instance. Hopefully that points you in the right direction? On a side note, if you're a junior developer being asked to write unit tests for a more senior developer get out now, your development team is rotten!
Sometimes, code is not written to be testable.
Especially calling constructors inside methods or other constructors is a big issue for unit testing and mocking.
If you do not use factories or dependency inversion / dependency injection in any way, you will have a very hard time testing the code. This is one of the reasons why CDI is so popular.
Anyways, being asked to write Unit Tests after Integration Tests are already in place is kind of a bad smell. You should have written the unit tests first. If you follow Test Driven Development (TDD), you should have written your test even before you actually wrote your class. This way, it would be impossible to write classes that are hard to test.
But what to do on your already messed up situation?
I recommend to refactor your code. Instead of calling a constructor inside your methods, pass an instance into your method, or provide a field in the class in order to be able to mock it.
Reconsider the scope of your unit test. It should only test a single class. Everything else, all the dependencies should be mocked.

Mocking a non-abstract method of an abstract class

I am trying to unit-test a class that extends an abstract base class.
Here are the "similar classes" for illustration purposes:
public abstract class MyAbstractBaseClass {
#Autowired
private WaterFilter waterFilter;
protected List<String> filterComponents(List<String> allComponents) {
return waterFilter.filter(allComponents);
}
}
public class MyDerivedClass extends MyAbstractBaseClass {
public List<String> filterWater(List<String> allWaterComponents) {
List<String> filteredComponents = this.filterComponents(allWaterComponents); //calls abstract class's filterComponets()
filteredComponents.add("something-else");
return filteredComponents;
}
}
Here is the unit test I am trying:
#RunWith(EasyMockRunner.class)
public class MyDerivedClassTest {
#TestSubject
private MyDerivedClassTest SUT;
#Before
public void setup() {
SUT = new MyDerivedClassTest();
}
#Test
public void test filterWater_HappyCase() {
//I want to mock my abstract class's filterComponents() method
//I am trying this:
EasyMock.expect(SUT.filterComponents(getDummyComponents())).andReturn(getSomeComponents());
//What to replay here?
//EasyMock.replay(...)
List<String> actualResult = SUT.filterWater(getDummyComponents());
//assert something
//What to verify?
//EasyMock.verify(...)
}
}
When I run this test, I get
java.lang.NullPointerException
in MyAbstractBaseClass.filter(allComponents)
I understand that the autowired "waterFilter" is not getting initialized. But then, I just want to mock the "non-abstract" method of the abstract class in my unit test.
How should I go about this using EasyMock? Also, I don't know what to replay() and verify().
When you write an unit test, you test a object (generally, a method of it) and you may mock a object (generally, a method of it).
However, you should not unit test and mock the same object because in a some way, it seems not very natural : if you test a method of a class, the behavior of the tested class should stay as natural as possible and not fake its own methods.
Otherwise, we can wonder if the quality of the unit test is good.
Why ? Because it doesn't reflect the real behavior of the class that we would have at the runtime, but just some part of its behavior.
In a unit test, isolation is researched but behind it, the idea is to isolate your under test class only from the other classes and not an isolation of its own behavior.
Of course, you can try to mock a no-abstract method in the abstract class of your under tested class but the design and the quality of your test may become less good.
In your case, I imagine two reasons to mock the no-abstract method in the abstract class :
the waterFilter field dependency annoys you because it is not valued, so an exception (NullPointerException) is raised during the test.
You really want to mock the no abstract method in the abstract class because you have already unitary tested this method and you don't want to duplicate this test.
1) If your the problem is the waterFilter field dependency.
you should mock the waterFilter field. To mock a field, it must be accessible and modifiable. In your case, it's not straight because the field is private.
So, you have two ways to access to it to be able to mock it :
change your design to give the possibility to set the field from a public method or in the constructor of MyDerivedClass.
use reflection to set the field (use an API or do it yourself because it's not hard).
You don't need to do verify operations with EasyMock. Just mock the result returned by waterFilter.filter(allComponents) such as :
waterFilterMock.filter(mockedComponents)
In this way, the mock returns the value you have chosen and in your JUnit assertion, you are able to do the correct assertion for your method under test.
Just for information, you could use Mockito instead of EasyMock. It's more flexible and it offers more readable operations.
For example, you could do it with Mockito :
Mockito.when(waterFilterMock.filter()).thenReturn(mockedComponents);
As you can see, it is more readable.
2) If you problem is that you really want to mock the no-abstract method in the abstract class because you have already unitary tested it
You should modify your design and use composition instead of inheritance. You would have not MyAbstractBaseClass any longer but simply a dependency between two classes (the one has a field of the other). In this way, you could mock the filterComponents() method in a natural way.
Expectations has to be set on mocked resources.
In your case i think you should inject a mocked instance of WaterFilter.
And your expectation,replay and verify should be set on waterFilter object instance.
You can refer to the example provided in given below link.
http://www.tutorialspoint.com/easymock/easymock_junit_integration.htm

what's the point using Mockito to mock objects? [duplicate]

In the program below, I am trying to use mockito with junit in my test case. But I don't see how Mokito is helping to create objects for my test? I don't see anything special here as it seems as if mokito is instantiating the actually object.
public class TestCase1{
#Mock
MyClass myClass;
public void setup(){
MokitoAnnotations.initMoks(this);
}
#Test
public void testAddition(){
when(myClass.add(2,2)).thenReturn(20);
assertEquals(4,myClass.add(2,2));
}
}
My actual class (MyClass.java)
public class MyClass{
public int add(int x, int y){
return x+y;
}
}
Is it mocking an object, the same as injecting(DI) an object? I appreciate your help!
Your test doesn't test any of your code. It tests that Mockito works fine.
When I introduce the concept of mocking, I take this example: suppose you build a detonator, and want to test it. You could of course use the detonator with a real bomb, and see if the whole block explodes when you use the detonator. But that isn't very practical. BTW, maybe you don't even have a bomb at your disposal. Maybe your colleague is still building it.
So you use a mock bomb. Note the important point: to test the detonator, you use a mock bomb. Not a mock detonator. What is mocked is the dependency of the class under test. Not the class under test itself.
What is a mock bomb? It's just a fake bomb that doesn't do anything. All it does is allowing to verify if has been asked to explode or not. So your code to test the detonator would be like this:
// create a mock bomb:
Bomb mockBomb = mock(Bomb.class);
// create a real detonator, but tie it to the mock bomb:
Detonator detonator = new Detonator(mockBomb);
// test the detonator. Since it's tied to a mock bomb, the block
// won't explode
detonator.pressTheRedButton();
// check it the mock bomb has been asked to explode, as it should
// if the detonator works correctly
verify(mockBomb).explode();
Now if the test passes, you know that all the internal circuitry that is used in pressTheRedButton() works fine and eventually tells the bomb to explode. So you know that, when used with a real bomb, the real bomb will be asked to explode as well when pressing the red button.
Now let's come back to the real world: you want to test a service, and this service uses a DAO that needs a database, populated with data, to run fine. To test your service, you can simply mock the DAO, and verify it works fine. The mock DAO can also be used as a stub, i.e. an object that returns what you tell it to return in the test, instead of actually querying the database. That's what you're doing in the code in your question: you're telling the mock MyClass instance that, when add() is called with 2 and 2 as arguments, it should return 4.
This makes the test easier to setup, faster to run, and independant from the actual code of the DAO, which is not what you want to test in the unit test of the service.

Junit and Mockito: How to test whether a method calls a method?

I'm trying to wrap my head around mockito and was wondering how I would test if a method calls a method!
So here is class with its method inside it:
public class RegisterController {
public void regHandle(UserDataObject user1){
ValidateRegisterInputController validate = new ValidateRegisterInputController();
validate.validateInputHandle(user1); }
How would I test that regHandle(UserDataObject) calls validate.validateInputHandle(user1); ?
I'm sure this is a super simple test, but I really can't figure out how to test this.
There are various ways of writing a test for a method which instantiates some other class. I wrote about two of them in my article on the Mockito wiki, at http://code.google.com/p/mockito/wiki/MockingObjectCreation
Both the techniques that I describe involve refactoring your code to make it more testable.
You would create a mock of ValidateRegisterInputController and then pass it on construction, then you would do:
Mockito.verify(mock).validateInputHandle(user1).
I strongly suggest you do not do this type of testing though. Instead of that, ask yourself how can you write an unit test that checks that what you wanted to validate was valid.
for example, check that after calling regHandle user1.isValid() is equals to true.

Having helper methods in junit class

I want to unit test a class, Class A, but it has a dependency on another class that uses a user session method. The method that I want to test does not involve user session. Can I make helper method in Class A that would replicate the behavior of the Class B method that I need?
I know it's not clear, let's dig some code to get clear understanding....
public void testDetails() throws Exception
{
//Some logic that generates DetailsTOList
saveDetailsHelper(DetailsTOList);
int detailsSize = getDetailsSize();
assertNotNull(detailsSize);
}
Now getDetailsSize() get size information from a database. Class B has this method, but I cannot create an object of Class B and test this method since Class B gets session information from User, and I can set session information from JUnit class.
I have created saveDetailsHelper method that replicates behavior of Class B - saveDetails() method, and am calling that in testDetails() method as shown above.
My question:
can we have helper methods in junit class?
What is best approach to deal with this situation?
JUnit classes function like every other class in java; you're welcome to have helper functions. The only thing that determines whether other functions will be run is (depending on the version of junit) whether or not there is an annotation instructing the harness to run it as a test.
However, this problem is precisely why you should design your classes carefully. If Class B calls out to a database for information, this is a great opportunity to compartmentalize that functionality. You don't clarify 'dependency' (are you extending?), but if Class B is a component of Class A, you can create a whole stub class that is a stand in for Class B, and returns hardcoded (or otherwise coded) data specifically for the testing of class A. As long as the signature of the Class B proxy is the same, you can have confidence Class A works.
It is often useful to make these inner classes of your test class, to keep things from getting too messy in your workspace.
public class testA {
#Test
public void testDetails {
ClassA a = new ClassA();
a.setDependency(new StubClassB());
//run your test
}
private class StubClassB() extends ClassB {
public boolean saveDetails() {
//return fake information;
}
}
}
Helper methods will not have the #Testcase annotation. You would write the test code just like any other code, but would include only the relevant methods for testing, and validate only relevant portions of that test method.
You can put the helper method in the test class, omit the Testcase annotation and call it where needed (ad hoc per method or in your setup if it's needed for all tests). But probably a better solution is to use something like JMock to represent Class B and give back desired results.

Categories