What is the difference between Mockito.mock(SomeClass) and the #Mock annotation? - java

What is the difference between Mockito.mock(Class<T> classToMock) method and the #Mock annotation?
Are they the same?
For Example, is this:
private TestClass test = Mockito.mock(TestClass.class);
the same as:
#Mock
private TestClass test;

They both achieve the same result. Using an annotation (#Mock) is usually considered "cleaner", as you don't fill up your code with boilerplate assignments that all look the same.
Note that in order to use the #Mock annotation, your test class should be annotated with #RunWith(MockitoJUnitRunner.class) or contain a call to MockitoAnnotations.initMocks(this) in its #Before method.

The difference is in the lines of code you need to write :) :) :)
Seriously though, using the annotations has the exact same effect as using the Mockito.mock.
To quote the documentation of MockitoAnnotations the use of annotations has the following benefits:
Allows shorthand creation of objects required for testing.
Minimizes repetitive mock creation code.
Makes the test class more readable.
Makes the verification error easier to read because field name is
used to identify the mock.
The javadoc for MockitoAnnotations is here

There are two significant advantages to using the annotation.
A mock created with #Mock can be injected into the class you're testing, using the #InjectMocks annotation. This is a powerful technique that can make testing significantly easier. It just won't work with mocks created by the mock method.
If you have any errors involving your mock, the name of the mock will appear in the message. If you've used #Mock, then this name will just be the name of the field. This makes it really easy to find the problem mock.
Of course, in addition to these two important advantages, most people find the #Mock notation much more readable, and it does cut down on the amount of code. I see no reason not to use it.

They both are considered same and achieve the same thing but I'd prefer the second one:
#Mock is an annotation which:
Minimizes repetitive mock creation code.
Makes the test class more readable.
Allows shorthand creation of objects required for testing.

The answer of the question is one big mistake.
We just solved some problems caused by Mockito.mock(Your.class) as a field.
We had few #Test methods. The 4th method was throwing an exception with 'thenThrow(ex)'. All of the #Test methods after it was failing and the reason was the exception thrown. They were sharing the mocked instance and the 'when' condition. After we changed from
TestClass testInstance = Mockito.mock(TestClass.class);
to
#Mock
TestClass testInstance;
everything started to work as expected. So Mockito.mock is creating a shared mock between the test methods, and #Mock does not.

In Junit5, use
#ExtendWith(MockitoExtension.class)

Related

Mockito initialize list of mock object behaviour

I ran into this problem when writing unit tests and took me a while to fix it. But still, I would like to understand what caused the discrepant behaviour:
1) Using Arrays.asList()
#Mock SomeClass obj;
List<SomeClass> list = Arrays.asList(obj);
This method doesn't work. It creates a list of size 1, with a null obj inside.
2) Adding mock during setup
#Mock SomeClass obj;
List<SomeClass> list = new ArrayList<>();
...
#Before
public void setup() {
list.add(obj);
}
This method works.
I'm just curious are the differences between the two methods, which might have caused one method to work but not the other?
The difference is based on the fact that the annotation #Mock has context. What I mean is: just putting an annotation somewhere into your source code isn't enough. You have to understand how exactly the annotation works.
And this mockito annotation is based on the various phases that the Junit framework relies on. The #Before method is executed every time before another #Test method gets executed.
So in your first snippet, that code gets run once, initially when the test class itself gets initialized. And at that point, the #Mock annotation hasn't done its magic. Therefore that code simply adds a null to your list.
So basically there is a misconception on your end. You assume that there is only the scope of the annotation that matters. But things are more complicated. This annotation relies on specific temporal aspects of the underlying framework.
The real answer is: whenever you encounter annotations, you have to study their documentation extremely carefully, as they are much more than just some Java language keyword.

Mockito, mocking a constructor within a method of a class

Currently trying to write unit tests for a complicated system that uses a constructor within one of its method that takes itself as the parameter to inject into a database context and retrieve the correct object from the correct environment.
Trying to use Mockito to emulate this, and make it return a test object instead of it going to try and find it from the database; but i'm stumped as to how to make it work with traditional techniques and #InjectMocks + #Mock annotations.
The essence of the code is below:
public FooService{
public String fooFindObject(FooDefinition fooDef) throws FooDefinitionException{
FooFinder theFooFinders = new FooFinder(this);
Foo fooObj = theFooFinders.findFoo(fooDef);
//Logic to be tested inside here that will throw exception upon bad foo definitions
return fooObj.trackingId();
}
How could I mock this FooFinder object and make it return my own testing foo object so I can test the definition obj. Mockito is being used, and the possiblity of rewriting this code to use get/setters of the FooFinder obj is not allowed - it's not my code and I'm just there to test it.
There is a library that extends upon Mockito: PowerMockito.
It allows you to do quite some more hacking than the usual Mockito. It's pretty sweet, but the thing is, if you need PowerMockito, your design usually smells.
I would definetely refactor your design. But if you can't do this for any reason, please take a look at constructor mocking with PowerMockito:
http://benkiefer.com/blog/2013/04/23/powermockito-constructor-mocking/

When to use when() in Mocktio

I am writing unit tests with JUnit and Mockito. Let's say I have following test class:
#Mock(name="myService")
private myServiceClass myService;
#InjectMocks
private myClassIWantToTest classUnderTest;
final myModelClass myModel = new myModelClass();
#Before
private void setUp(){
MockitoAnnotiations.initMocks(this);
}
#Test
private void testSomething(){
myModel.setCode("someCode");
final MyDataClass myData = new MyDataClass();
myData.setCode("someCode");
doReturn("someCode").when(myModel.getCode());
doReturn(myModel).when(myService.getModelByCode("someCode"));
assertEquals(classUnderTest.getDataByCode(eq("someCode")), myData);
verify(myService.getModelByCode(eq("someCode")), atLeastOnce());
}
The method getDataByCode from my classUnderTest converts the Model into Data and it should have the same code. What is a bit blurry to me is that unit tests should encapsule the classUnderTest from all dependencies. But now I have a problem. I use the setter methods myData and myModel to set a value. The thing is I put a DoReturn in there for myModel, but the problem is, that it's not a injected Mock. The method I try to test unfortunately doesn't have a field, it initializes this inside the method, so I can't really address it.
And the main thing is, when the setter of for example myModel doesn't work anymore or so, my test as shown above, wouldn't work anymore. I guess I have three questions:
How hard do I need to isolate the test class? Don't I need to use the setters for the assertEquals?
Is there another way to deal with objects, which are initialized inside a method I want to test? What is the best way to approach such a matter?
Also, what would be a good pattern for structuring this? I currently initialize my expected myData result inside a test method. The thing is that this is a rather short and easy example, but I have classes where I have tons of objects and methods.
Sounds like your main problem is the design of the class you want to test. But a few things before:
myModel.setCode("someCode");
doReturn("someCode").when(myModel.getCode());
This doesn't make sense. It's not a mock, so do...when doesn't make sense here. And if it was a mock, calling the setter would be useless.
assertEquals(classUnderTest.getDataByCode(eq("someCode")), myData);
Also strange. You want to call getDataByCode, why the eq? Do it. Call it. Write:
assertEquals(classUnderTest.getDataByCode("someCode"), myData);
Mockito-Matchers are good when you want to verify something but normally you don't use them as parameters for real method calls.
verify(myService.getModelByCode(eq("someCode")), atLeastOnce());
Does this code really compile? Shouldn't it be ...
verify(myService, atLeastOnce()).getModelByCode(eq("someCode"));
So, it would be a good idea to actually isolate your unit tests as far as you can. The less external problems you are inviting into your test, the better the test can be.
The method I try to test unfortunately doesn't have a field, it
initializes this inside the method, so I can't really address it.
This simply sounds like a code smell, but without the actual code in question, it's hard to say...

Mockito method call without object

The code has something like
Speed speed = readSpeed(Point A, Point B);
isOverLimit = limitCheck.speedCheck(speed);
How do I use mockito for read speed?
Mockito.when(readSpeed(0, 0).then...
suppose should I use the class object to call this?
Mockito effectively works by creating individual subclasses of objects that delegate every overridable implementation to the mock framework.
Consequently, you can't use Mockito mock your method (readSpeed) for all instances at once or instances created in your system under test, nor mock any static or final methods. If readSpeed is any of those, or need to be mocked on an instance you don't touch in your test, Mockito will not work for you; you'll need to refactor, or use PowerMockito (which quietly rewrites your system under test to redirect constructors, final calls, and static calls to Mockito's framework).
If readSpeed is a public non-final instance method on your system under test, then you can mock it, and that'd be called a partial mock of your component. Partial mocks can be useful, but can also be considered "code smells" (as mentioned in the Mockito documentation): Ideally your test class should be an atomic unit to test, and mocking should happen for the dependencies around your system under test rather than your test itself. Otherwise, you could too easily test the spec or test the mocking framework rather than testing your component.
Though the better thing to do would be to split the class into smaller interconnected components, you can use partial mocking in Mockito like this:
#Test public void componentChecksSpeed() {
YourComponent yourComponent = Mockito.spy(new YourComponent());
// Use doReturn, because the when syntax would actually invoke readSpeed.
doReturn(65).when(yourComponent).readSpeed(any(Point.class), any(Point.class));
yourComponent.run();
}

Mockito: Mock and inject a mocked class

I currently am faced with the following test case:
I want to mock the abstract ActorRef class from akka:
#RunWith(MockitoJUnitRunner.class)
public class ConstraintBuilderTest {
#Mock
ClassANeededByClassB a;
#InjectMock
ClassB b;
#Before
public void setUp(){
Mockito.when(a.equals(a)).thenReturn(true);
}
//tests go here
}
I know that the mockito page says it cannot mock equals. So are there any ideas on how to mock that?
The equals method on ClassB uses ClassANeededByClassB to check its equality.
What I could think of to do is to inject a into the mocked class b. How best to proceed?
Please be aware that the classes come from a framework which I cannot change, so I cannot change its code to add a setter or anything like that.
b is a mock, so you shouldn't need to inject anything. After all it isn't executing any real methods (unless you explicitly do so with by calling thenCallRealMethod), so there is no need to inject any implementation of ClassANeededByClassB.
If ClassB is the class under test or a spy, then you need to use the #InjectMocks annotation which will inject any matching mocks into ClassB.
#RunWith(MockitoJUnitRunner.class)
public class ConstraintBuilderTest {
#Mock
ClassANeededByClassB a;
#InjectMocks
ClassB b;
// ...
}
As you said, Mockito doesn't support mocking equals. There might be some workarounds but I don't know any. So here's just some thoughts about it in general:
Mockito's approach is that if you can't mock something with Mockito, it probably is badly designed and should be refactored. I know it's not your code, and that actually leads to the next point:
"Don't test the framework". You likely don't need to test this part at all - it should be the responsibility of the frameworks creators to test it. You could try to contribute a patch if it is an open source project.
Mockito has some self-imposed limitations, so it might just not be the right tool for this job. There are other mocking frameworks that are more powerful and capable of doing this.

Categories

Resources