I have a service ISOLanguageService with a method getDefaultLanguage();
I want to mock this service in one class ISOLanguageServiceMock in this way:
public class ISOLanguageServiceMock {
#Mock
private ISOLanguageService isoLanguageService;
public ISOLanguageServiceMock() {
MockitoAnnotations.initMocks(this);
ISOLanguage isoLanguage = new ISOLanguage();
isoLanguage.setLanguageCode("EN");
when(isoLanguageService.getDefaultLanguage()).thenReturn(isoLanguage);
}
Then i have other service UserService that uses this service isoLanguageService in one of its metdhods.
public void doSomtthing() {
return isoLanguageService.getDefaultLanguage()
}
I want to test the UserService but i want in someway to reuse the mock ISOLanguageServiceMock because it's going to be used in many other services.
I want Something like this
#RunWith(PowerMockRunner.class)
public class UserServiceTest {
private ISOLanguageServiceMock languageMock = new ISOLanguageServiceMock();
#InjectMocks
private UserService userService;
public void setUp() {
MockitoAnnotations.init(this)
}
public void testDoSomething() {
userService.doDomething();
}
}
I'd like that the mock for isoLanguageService be injected in the userService, but it's not...
Is there anyway to reuse a mocks ?? Do i have to write in every test class the mock for isoLanguageService ??
You can't reuse mocks this way. You need #Mock instances to be in your test case, and use them there.
Meaning:
#Mock
private ISOLanguageService isoLanguageService;
and specifications for into your UserServiceTest class.
Mockito does not understand (or care) that your ISOLanguageServiceMock class contains something that could be injected into the class under test.
Mockito looks for the mocks you have in your test class, and those get injected, nothing else!
Regarding the re-use aspect:
you could do that by subclassing (having a base class with that #Mock field)
but then, that is bad practice, to a certain degree. Unit tests should be self contained, as much as possible. It is okay when unit tests duplicate code, because you want to be able to look at one file (your test case) to understand what is going on).
Meaning: (in general), code duplication within unit tests isn't that crucial. The goal of unit tests is to enable quick debugging.
Well, some alternatives:
you can of course, not use #InjectMocks. In that case, your production code needs another way for you to inject mocked objects yourself (either setters, or test only constructors).
when you inject manually, you can of course inject whatever mock object you want to, even one that comes from another class
but then: no extra class required, simply have a static method somewhere that returns a (pre-configured) mock.
Related
I am learning TDD and I have some doubts when usings Mocks with mockito and junit.
Without mocks:
Contacto contacto = new Contacto("Santiago", "3022653192", "santi-1524#hotmail.com");
agenda.agregarContacto(contacto);
Assert.assertEquals(1, agenda.getSizeOfAgenda());
agenda.agregarContacto(contacto);
With mocks:
Mockito.verify(agenda).agregarContacto(contacto);
Mockito.when(agenda.getSizeOfAgenda()).thenReturn(1);
Assert.assertEquals(1, agenda.getSizeOfAgenda());
if I do the test without the mocks it takes less time than doing the test with Test for example: 2ms vs 356ms.
what are the benefits of doing the test with Mockito in this case?
Kind of missing the point of mocking. You use mocks to ensure ( mock ) the behavior of the surrounding services / external dependencies and everything that do not have to do directly with what you want to test.
In your example if you test your agenda service you will mock the contact as its irrelevant what contents it has as long as a contact goes in the agenda. If you also had lets say a calendar in the agenda you would mock that calendar also.
what are the benefits of doing the test with Mockito in this case?
In your case mocking was used in the wrong way.
A clear example of why you want to mock is a Service that will save something to your database.
public class SomeService {
private SomeRepository repo;
public SomeService(SomeRepository repo){
this.repo = repo;
}
public YourClass save(YourClass clazz){
repo.save(clazz);
}
}
public class SomeRepository {
private Connection yourDatabaseConnection;
public YourClass save(YourClass clazz){
yourDatabaseConnection.save(clazz);
}
}
So lets not bother how the connection is setup. When you will run a test from SomeService this will call your repo thus saving something in your database. Meaning you will have to setup a database and take care of the data inside which may create problems if you run multiple tests or tests in parallel ( if you and one of your colleges run the same test with you at the same time ). All this is a fuss and goes outside the unit-testing theory. Your unit is the Service in this scenario the SomeService. So you only need to test this.
#Test
public void test(){
final SomeRepository repo = mock(SomeRepository.class);
final SomeService serv = new SomeService(repo);
final YourClass clazz = mock(YourClass.class);
when(repo.save(clazz)).thenReturn(clazz);
YourClass response = serv.save(clazz);
Assert.assertEquals(clazz,response);
verify(repo).save(clazz);
}
This way you validate your service returns your object without any mutations in the middle as this was the expected behavior from the setup above. You validate it called the repository but you never actually calling it. This way no data will be added in your database ( meaning you dont need a database ) and the test is isolated and can be run in parallel a million times and it always have the same result.
I am fairly new to mockito framework. I've been reading upon multiple tutorials in regards to it. One of them I was following is this: https://www.tutorialspoint.com/mockito/mockito_first_application.htm
There is a statement creating a mock of Stock Service.
In this example, we've created a mock of Stock Service to get the dummy price of some stocks
My question is Stock Service is a real service class or mock service class you have to manually stand up for mimicking the real service class. I am a bit confused. Having basic understanding of junit framework. What I had practiced before was if there is a service class Foo then I used actual class that provides all the exposed methods.
public class Foo {
public Foo() { } // construtor
public String returnAddress(String userId) {
// ...
return dataAccesobj.getAddress(userId);
}
}
Calling foo.returnAddress(..) in unit test if I remember right.
The reason I am asking this question is while I was working with mockitoto create a test method for a class, I ran into a unique(?) challenge.
I started with a real service class which depends on its super class constructor to return its instance. The challenge I ran into was this super class constructor initiates DB connection and loading/parsing properties files which I do not need for my test. I was thinking about how to prevent DB connection and loading/reading prop files....
I thought I read from one of mockito tutorials you can isolate testing without having such services. I tried with #Mock and #Spy (not fully understanding well still what they are for..) but it didn't make a difference for output (maybe I misused those annotations).
So what I did was actually creating fake/mock class out of real service class (e.g. Foo) by simply copying it and renamed it as FooMock and put it in src/test/java folder in where unit test class is running from. I kept the mock class exactly same as the real service class except taking out unwanted logic such as db connection or loading/reading prop file for env specific. By doing that I was able to test one of exposed methods that read ldap directory...
I am sorry I got digressed but hope my point is clear at this point. I am not sure the way I handled this situation is right or wrong. I'd appreciate experienced engineers would clarify the way I handled the matter is acceptable in mockito way or not. If not, then plz advise me best way to handle it.
With Mockito,
a mock is an implementation of a wrapper class.
The mock object "wraps" the target of the mock
(the service in your example)
and allows you to define functionality of each method.
There are two mocked functionality options with Mockito;
call the wrapped method and don't call the wrapped method.
I don't know when it would make sense to call the wrapped method,
so I always use don't call the wrapped method.
After you create the mock,
use the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) method to mock functionality.
Edit: some more info.
I will assume that you are using junit v4.
The details of this will differ based on the the junit major release number,
but the actual work will be the same.
Use annotations to define your Mock objects (#Mock),
except in a few special cases.
This will create mocks of non-final classes,
abstract classes,
and interfaces.
Create a "before-test" method using the #Before annotation;
I traditionally name this method preTestSetup,
but the actual name does not matter.
Call MockitoAnnotations.initMocks(this) as the first line of code
in the "before-test" method.
This will find the #Mock annotations and instantiate a mock for each.
Use the ReflectionTestUtils.setField method to inject the mocks into your object (assuming that you don't have setter methods,
which I traditionally don't like).
Define the mocked functionality of each method using the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) technique.
Here is some example code
(caveat:
this should be fully functional,
but I did not compile it):
public interface MyService
{
String blammy(SomeParameter parameter);
}
public class UsesMyService
{
#Autowired
private MyService myService;
public String kapow(final SomeParameter parameter)
{
return myService.blammy(parameter);
}
}
public class UnitTestUsesMyService
{
private UsesMyService classToTest;
#Mock
private MyService mockMyService;
#Mock
private SomeParameter mockSomeParameter;
#Before
public void preTestSetup()
{
MockitoAnnotations.initMocks(this);
classToTest = new UsesMyService();
doReturn("Blam").when(mockMyService).blammy(mockSomeParameter);
ReflectionTestUtils.setField(
classToTest,
"myService",
mockMyService);
}
#Test
public void kapow_allGood_success()
{
final String actualResult;
actualResult = classToTest.kapow(mockSomeParameter);
assertNotNull(actualResult); // Not strictly necessary.
assertEquals(
"Blam",
actualResult);
}
}
I have gone through some of the blogs in order to understand the basics of how Mockito annotations work.
However I am facing a doubt as to when does one go for manually instantiating the field annotated with #InjectMocks i.e
#InjectMocks
A a = new A();
And when does one rely on MockitoAnnotations.initMocks() functionality to do the same :
#InjectMocks
A a;
Does this depend on the JunitTestRunner that we employ to run the test cases or is it dependent on the Mockito framework version?
It depends if you are using (declaring) the runner or not.
If you use the runner, you don't need to call MockitoAnnotations.initMocks() yourself - the runner calls it for you.
Usually we go for the runner. When you want to use other runners, though (like Spring's), you can call .initMocks() yourself.
Just to be clear, the MockitoAnnotations.initMocks(this) will:
Instantiate the field annotated with #InjectMocks
Create a mock version of every field annotated with #Mock
Inject the #Mocks in the #InjectMocks variable's fields (or call its constructors or use its setters - it depends on what kind of Dependency Injection you use)
Mockito runner, initMocks and rule code samples
The three code samples below should be equivalent.
With runner:
This first snippet uses the runner, making the call to initMocks() unnecessary.
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock private MyDependency myDependency;
#InjectMocks private MyClass myClass;
#Test
public void myClass_should_get_stuff_from_dependency() {
when(myDependency.getStuff()).thenReturn("stuff!");
assertThat(myClass.getDependencyStuff(), is("stuff!"));
}
}
Without runner + with manual call to .initMocks():
This other does not use the runner, thus the need for the setUp() method calling our initMocks() friend.
// notice there is no runner
public class MyClassTest {
#Mock private MyDependency myDependency;
#InjectMocks private MyClass myClass;
// but now you have to call initMocks() yourself
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void myClass_should_get_stuff_from_dependency() {
when(myDependency.getStuff()).thenReturn("stuff!");
assertThat(myClass.getDependencyStuff(), is("stuff!"));
}
}
Without runner or manual call, using #Rule:
Finally, as pointed out in the comments (thanks #StefanBirkner), since version 1.10.17, there is also the possibility of using a JUnit #Rule called MockitoRule:
public class MyClassTest {
#Rule
public MockitoRule rule = MockitoJUnit.rule();
#Mock private MyDependency myDependency;
#InjectMocks private MyClass myClass;
#Test
public void myClass_should_get_stuff_from_dependency() {
when(myDependency.getStuff()).thenReturn("stuff!");
assertThat(myClass.getDependencyStuff(), is("stuff!"));
}
}
In general, the decision to instantiate an object which is annotated with #InjectMocks or not is a code style choice. In the majority of cases there will be no difference as Mockito is designed to handle both situations.
However, there is some differences which I have outlined below.
#InjectMocks decouples a test from changes to the constructor.
In the same way using a Dependency Injection framework decouples your production code from changes to the constructor. Allowing Mockito to instantiate an instance of the class for you decouples your test code from changes to the constructor. This means any future changes to the class constructor can be done without causing compilation errors in the unit test.
In my opinion this is the biggest difference and the biggest advantage of #InjectMocks.
Mockito will always call the "biggest" constructor
Note: This difference is only relevant when the code you are working with does not follow best practices.
When there is multiple constructors in a class, Mocktio will call the constructor with the most parameters, the "biggest" constructor.
This only has an impact when,
A "small" constructor contains logic.
This logic is required for the class to function correctly.
The "biggest" constructor does not invoke the next "smallest" constructor.
This is considered bad practice because,
Placing logic within a constructor should be avoided whenever possible.
When there is multiple constructors within a class each constructor should first invoke the constructor before it.
Thanks for your valuable thoughts.
But still it doesn't answer the question as to why one goes for manually instantiating the field annotated with #InjectMocks when the instantiation should be handled by a call to MockitoAnnotations.initMocks().
I get the following error when trying to run the test file :
Caused by: org.mockito.exceptions.base.MockitoException: Field 'student' annotated with #InjectMocks is null.
Please make sure the instance is created before MockitoAnnotations.initMocks();
Example of correct usage:
class SomeTest {
#InjectMocks private Foo foo = new Foo();
#Before public void setUp() {
MockitoAnnotations.initMock(this);
I searched further and found out that the error is thrown if one is using an older version of Mockito framework.
http://myshittycode.com/category/testing/mockito/
I'm using Mockito's #Mock and #InjectMocks annotations to inject dependencies into private fields which are annotated with Spring's #Autowired:
#RunWith(MockitoJUnitRunner.class)
public class DemoTest {
#Mock
private SomeService service;
#InjectMocks
private Demo demo;
/* ... */
}
and
public class Demo {
#Autowired
private SomeService service;
/* ... */
}
Now I would like to also inject real objects into private #Autowired fields (without setters). Is this possible or is the mechanism limited to injecting Mocks only?
Use #Spy annotation
#RunWith(MockitoJUnitRunner.class)
public class DemoTest {
#Spy
private SomeService service = new RealServiceImpl();
#InjectMocks
private Demo demo;
/* ... */
}
Mockito will consider all fields having #Mock or #Spy annotation as potential candidates to be injected into the instance annotated with #InjectMocks annotation. In the above case 'RealServiceImpl' instance will get injected into the 'demo'
For more details refer
Mockito-home
#Spy
#Mock
In Addition to #Dev Blanked answer, if you want to use an existing bean that was created by Spring the code can be modified to:
#RunWith(MockitoJUnitRunner.class)
public class DemoTest {
#Inject
private ApplicationContext ctx;
#Spy
private SomeService service;
#InjectMocks
private Demo demo;
#Before
public void setUp(){
service = ctx.getBean(SomeService.class);
}
/* ... */
}
This way you don't need to change your code (add another constructor) just to make the tests work.
In Spring there is a dedicated utility called ReflectionTestUtils for this purpose. Take the specific instance and inject into the the field.
#Spy
..
#Mock
..
#InjectMock
Foo foo;
#BeforeEach
void _before(){
ReflectionTestUtils.setField(foo,"bar", new BarImpl());// `bar` is private field
}
Mockito is not a DI framework and even DI frameworks encourage constructor injections over field injections.
So you just declare a constructor to set dependencies of the class under test :
#Mock
private SomeService serviceMock;
private Demo demo;
/* ... */
#BeforeEach
public void beforeEach(){
demo = new Demo(serviceMock);
}
Using Mockito spy for the general case is a terrible advise. It makes the test class brittle, not straight and error prone : What is really mocked ? What is really tested ?
#InjectMocks and #Spy also hurts the overall design since it encourages bloated classes and mixed responsibilities in the classes.
Please read the spy() javadoc before using that blindly (emphasis is not mine) :
Creates a spy of the real object. The spy calls real methods unless
they are stubbed. Real spies should be used carefully and
occasionally, for example when dealing with legacy code.
As usual you are going to read the partial mock warning: Object
oriented programming tackles complexity by dividing the complexity
into separate, specific, SRPy objects. How does partial mock fit into
this paradigm? Well, it just doesn't... Partial mock usually means
that the complexity has been moved to a different method on the same
object. In most cases, this is not the way you want to design your
application.
However, there are rare cases when partial mocks come handy: dealing
with code you cannot change easily (3rd party interfaces, interim
refactoring of legacy code etc.) However, I wouldn't use partial mocks
for new, test-driven & well-designed code.
I know this is an old question, but we were faced with the same problem when trying to inject Strings. So we invented a JUnit5/Mockito extension that does exactly what you want: https://github.com/exabrial/mockito-object-injection
EDIT:
#InjectionMap
private Map<String, Object> injectionMap = new HashMap<>();
#BeforeEach
public void beforeEach() throws Exception {
injectionMap.put("securityEnabled", Boolean.TRUE);
}
#AfterEach
public void afterEach() throws Exception {
injectionMap.clear();
}
I have a simple unit test where in I test a DAO. I mock the dependency and inject it into the subject through the constructor.
Do I need a tear down? Does Mockito test exit at the same state it entered the setup method? Please also explain.
#Mock
private PersonDAO dao;
#Overide
public void setup(){
MockitoAnnotations.initMocks(this);
sut = new PersonResource(dao);
}
#Test
public void testUpdate(){
when(dao.findNameById(1)).thenReturn("Abhinav-before");
sut.update(1, "Abhinav-after");
}
Unless you're pulling in other state-driven resources, such as a cache, or a temp file, you don't need to tear down any resources when mocking.
A mock object is just an object; it doesn't have or maintain anything to external services. It will get garbage collected just like any other object you have in your test. Depending on how you're injecting the mock, it's recreated for every test run, anyway.
Now that you've provided a little bit of code, had you used the #Before annotation, you would be sure that both the mock gets injected before each instance of the test run. As it stands, that test probably doesn't compile; I can't imagine a scenario in which you would have that test extend another test that has a setup method.
(And if you do, please don't. You'll only hurt yourself.)
Lastly, assert something in this test. You're not asserting anything, so it'll always pass unless you assert something to be true about the state of your test object.
With that bit out of the way, if you use MockitoJUnitRunner instead, you don't require the initMocks piece, but this is only applicable if this is your only runner as JUnit can't support multiple runners.
#RunWith(MockitoJUnitRunner.class)
public class PersonResourceTest {
#Mock
private PersonDAO dao;
#InjectMocks
private PersonResource testObject;
#Test
public void testUpdate(){
when(dao.findNameById(1)).thenReturn("Abhinav-before");
testObject.update(1, "Abhinav-after");
}
}