Manually instantiating the #InjectMock annotated field - java

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/

Related

Is it possible to reuse mocks ?

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.

Mockito - NullpointerException when stubbing Method

So I started writing tests for our Java-Spring-project.
What I use is JUnit and Mockito. It's said, that when I use the when()...thenReturn() option I can mock services, without simulating them or so. So what I want to do is, to set:
when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)
But no matter which when-clause I do, I always get a NullpointerException, which of course makes sense, because input is null.
Also when I try to mock another method from an object:
when(object.method()).thenReturn(true)
There I also get a Nullpointer, because the method needs a variable, which isn't set.
But I want to use when()..thenReturn() to get around creating this variable and so on. I just want to make sure, that if any class calls this method, then no matter what, just return true or the list above.
Is it a basically misunderstanding from my side, or is there something else wrong?
Code:
public class classIWantToTest implements classIWantToTestFacade{
#Autowired
private SomeService myService;
#Override
public Optional<OutputData> getInformations(final InputData inputData) {
final Optional<OutputData> data = myService.getListWithData(inputData);
if (data.isPresent()) {
final List<ItemData> allData = data.get().getItemDatas();
//do something with the data and allData
return data;
}
return Optional.absent();
}
}
And here is my test class:
public class Test {
private InputData inputdata;
private ClassUnderTest classUnderTest;
final List<ItemData> allData = new ArrayList<ItemData>();
#Mock
private DeliveryItemData item1;
#Mock
private DeliveryItemData item2;
#Mock
private SomeService myService;
#Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
myService = mock(myService.class);
classUnderTest.setService(myService);
item1 = mock(DeliveryItemData.class);
item2 = mock(DeliveryItemData.class);
}
#Test
public void test_sort() {
createData();
when(myService.getListWithData(inputdata).get().getItemDatas());
when(item1.hasSomething()).thenReturn(true);
when(item2.hasSomething()).thenReturn(false);
}
public void createData() {
item1.setSomeValue("val");
item2.setSomeOtherValue("test");
item2.setSomeValue("val");
item2.setSomeOtherValue("value");
allData.add(item1);
allData.add(item2);
}
I had this issue and my problem was that I was calling my method with any() instead of anyInt(). So I had:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())
and I had to change it to:
doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())
I have no idea why that produced a NullPointerException. Maybe this will help the next poor soul.
The default return value of methods you haven't stubbed yet is false for boolean methods, an empty collection or map for methods returning collections or maps and null otherwise.
This also applies to method calls within when(...). In you're example when(myService.getListWithData(inputData).get()) will cause a NullPointerException because myService.getListWithData(inputData) is null - it has not been stubbed before.
One option is create mocks for all intermediate return values and stub them before use. For example:
ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);
Or alternatively, you can specify a different default answer when creating a mock, to make methods return a new mock instead of null: RETURNS_DEEP_STUBS
SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);
You should read the Javadoc of Mockito.RETURNS_DEEP_STUBS which explains this in more detail and also has some warnings about its usage.
I hope this helps. Just note that your example code seems to have more issues, such as missing assert or verify statements and calling setters on mocks (which does not have any effect).
I had the same problem and my issue was simply that I had not annotated the class properly using #RunWith. In your example, make sure that you have:
#RunWith(MockitoJUnitRunner.class)
public class Test {
...
Once I did that, the NullPointerExceptions disappeared.
For future readers, another cause for NPE when using mocks is forgetting to initialize the mocks like so:
#Mock
SomeMock someMock;
#InjectMocks
SomeService someService;
#Before
public void setup(){
MockitoAnnotations.initMocks(this); //without this you will get NPE
}
#Test
public void someTest(){
Mockito.when(someMock.someMethod()).thenReturn("some result");
// ...
}
Also make sure you are using JUnit for all annotations.
I once accidently created a test with #Test from testNG so the #Before didn't work with it (in testNG the annotation is #BeforeTest)
For me the reason I was getting NPE is that I was using Mockito.any() when mocking primitives. I found that by switching to using the correct variant from mockito gets rid of the errors.
For example, to mock a function that takes a primitive long as parameter, instead of using any(), you should be more specific and replace that with any(Long.class) or Mockito.anyLong().
Hope that helps someone.
As this is the closest I found to the issue I had, it's the first result that comes up and I didn't find an appropriate answer, I'll post the solution here for any future poor souls:
any() doesn't work where mocked class method uses a primitive parameter.
public Boolean getResult(String identifier, boolean switch)
The above will produce the same exact issue as OP.
Solution, just wrap it:
public Boolean getResult(String identifier, Boolean switch)
The latter solves the NPE.
keep in mind if you choose this approach, now you might want to include a nullcheck for Boolean in production code (credit: brought up by Ridcully)
Make sure you initialize your mocks.
JUnit4 use #Before
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
JUnit5 use #BeforeEach
#BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
For JUnit5 check, you are using proper imports also.
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
Corner case:
If you're using Scala and you try to create an any matcher on a value class, you'll get an unhelpful NPE.
So given case class ValueClass(value: Int) extends AnyVal, what you want to do is ValueClass(anyInt) instead of any[ValueClass]
when(mock.someMethod(ValueClass(anyInt))).thenAnswer {
...
val v = ValueClass(invocation.getArguments()(0).asInstanceOf[Int])
...
}
This other SO question is more specifically about that, but you'd miss it when you don't know the issue is with value classes.
For JUnit 5 the test class has to be annotated with:
#ExtendWith(MockitoExtension.class)
imports:
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
My issue was fixed with this addition.
you need to initialize MockitoAnnotations.initMocks(this) method has to called to initialize annotated fields.
#Before public void initMocks() {
MockitoAnnotations.initMocks(this);
}
for more details see Doc
Check that the method signature is not declared as final
This one catches out a lot of people who work on codebases which are subjected to Checkstyle and have internalised the need to mark members as final.
i.e. in the OP's example:
object.method()
Make sure that method() is not declared as final:
public final Object method() {
}
Mockito cannot mock a final method and this will come up as a wrapped NPE:
Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Buried deep in the error message is the following:
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
None of the above answers helped me. I was struggling to understand why code works in Java but not in Kotlin.
Then I figured it out from this thread.
You have to make class and member functions open, otherwise NPE was being thrown.
After making function open tests started to pass.
You might as well consider using compiler's "all-open" plugin:
Kotlin has classes and their members final by default, which makes it inconvenient to use frameworks and libraries such as Spring AOP that require classes to be open. The all-open compiler plugin adapts Kotlin to the requirements of those frameworks and makes classes annotated with a specific annotation and their members open without the explicit open keyword.
For me, it was because I was stubbing the mock in the #BeforeAll method.
MockitoExtension does not have a callback for #BeforeAll.
public class MockitoExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver
I moved the stubbing inside the test method it worked!!
In my case, it was the wrong import for when().
I used import static reactor.core.publisher.Mono.when by accident.
In my case, Intellij created Test with org.junit.jupiter.api.Test (Junit5) instead of import org.junit.Test of (Junit4) which caused all beans to be null apparently.
also, make sure the class and test method is public
In my case, my Mockito annotation didn't match the JUnit Version.
When using #ExtendWith(MockitoExtension.class) make sure you're using JUnit 5: import org.junit.jupiter.api.Test;
When using #RunWith(MockitoJUnitRunner.class) make sure you're using JUnit 4: import org.junit.Test;
In my case, I missed add first
PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);
so this can be helpful to somebody who see such error
java.lang.NullPointerException
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:42)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:112)
#RunWith(MockitoJUnitRunner.class) //(OR) PowerMockRunner.class
#PrepareForTest({UpdateUtil.class,Log.class,SharedPreferences.class,SharedPreferences.Editor.class})
public class InstallationTest extends TestCase{
#Mock
Context mockContext;
#Mock
SharedPreferences mSharedPreferences;
#Mock
SharedPreferences.Editor mSharedPreferenceEdtor;
#Before
public void setUp() throws Exception
{
// mockContext = Mockito.mock(Context.class);
// mSharedPreferences = Mockito.mock(SharedPreferences.class);
// mSharedPreferenceEdtor = Mockito.mock(SharedPreferences.Editor.class);
when(mockContext.getSharedPreferences(Mockito.anyString(),Mockito.anyInt())).thenReturn(mSharedPreferences);
when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.remove(Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
when(mSharedPreferenceEdtor.putString(Mockito.anyString(),Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
}
#Test
public void deletePreferencesTest() throws Exception {
}
}
All the above commented codes are not required
{ mockContext = Mockito.mock(Context.class); },
if you use #Mock Annotation to Context mockContext;
#Mock
Context mockContext;
But it will work if you use #RunWith(MockitoJUnitRunner.class) only. As per Mockito you can create mock object by either using #Mock or Mockito.mock(Context.class); ,
I got NullpointerException because of using #RunWith(PowerMockRunner.class), instead of that I changed to #RunWith(MockitoJUnitRunner.class) it works fine
Well in my case it was because of wrong annotation usage. I was using junit 4 for testing and used #BeforeEach instead of #Before while initializing.
Changed it to #Before and it works like charm.
This is where google took me when I had the same NullPointerException with Junit 5, but was correctly using #ExtendWith(MockitoExtension.class) in my maven project.
Turns out I hadn't included the maven-surefire-plugin in my pom.xml and that meant the #ExtendWith wasn't actually doing anything!
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
...
I was using wrong annotation/import of Mock, so my object was not getting formed.
I was using org.evosuite.shaded.org.mockito.Mock and I switched back to org.mockito.Mock. Then as if by magic, it started working for me.
Ed Webb's answer helped in my case. And instead, you can also try add
#Rule public Mocks mocks = new Mocks(this);
if you #RunWith(JUnit4.class).
None of these answers worked for me. This answer doesn't solve OP's issue but since this post is the only one that shows up on googling this issue, I'm sharing my answer here.
I came across this issue while writing unit tests for Android. The issue was that the activity that I was testing extended AppCompatActivity instead of Activity. To fix this, I was able to just replace AppCompatActivity with Activity since I didn't really need it. This might not be a viable solution for everyone, but hopefully knowing the root cause will help someone.
When using JUnit 5 or above. You have to inject the class annotated with #Mock
in an #BeforeEach setup.
In my case it was due to wrong import of the #Test annotation
Make sure you are using the following import
import org.junit.jupiter.api.Test;
Annotate the test class with: #ExtendWith(MockitoExtension.class).
In my case a tested method called another method as a parameter:
Mockito.`when`(repository.getItems(prefs.getUser().id)).thenReturn(listOf())`
While repository is mocked, prefs.getUser().id) will throw NPE. So, first we should mock a parameter, for instance,
Mockito.`when`(prefs.getUser()).thenReturn(User(id = 1, name = "user"))`
Also we should mock prefs. I didn't check it and changed a library, sorry.
I was trying to mock a "final" method, which apparently was the problem.
The right way to handle this would be to use an interface and mock that interface however I couldn't control the library where the "final" method was.
Mockito 2 can handle mocking final method. Add a text file to the project's src/test/resources/mockito-extensions directory named org.mockito.plugins.MockMaker and add a single line of text:
mock-maker-inline
After that, mocking the final method should work just fine.
Check which version of Junit you are using. In the Maven/Gradle build tool, if you set to use testRuntimeOnly 'junit5',then it might not take #RunWith since it is not available and it is replaced with #ExtendWith in Junit5.
This doesnt answer the OP's original query, but its here to try help others with Mockito null pointer exceptions (NPE).
My NPE was happening as I did not explicitly set the class under tests' dependencies to be the classes I had mocked. So the class under test was unable to find its required dependencies, creating the NPE. I tend to not mock the class under test (i.e. use new keyword), to ensure im getting my native class behaviour for testing.
Im still using Junit 4 for reasons outside my control. Worked example;
ClassUnderTest
public class ClassUnderTest {
private DependantClassOne dependantClassOne;
private DependantClassTwo dependantClassTwo;
// remaining class, including setters
}
Test Class
#RunWith(MockitoJUnitRunner.class)
public class Test {
private ClassUnderTest classUnderTest;
private DependantClassOne dependantClassOne;
private DependantClassTwo dependantClassTwo;
#Before
public void setup() {
dependantClassOne = mock(DependantClassOne.class);
dependantClassTwo = mock(DependantClassTwo.class);
classUnderTest = new ClassUnderTest();
classUnderTest.setDependantClassOne(dependantClassOne); //added to prevent NPE
classUnderTest.setDependantClassTwo(dependantClassTwo); //added to prevent NPE
}
// tests
}

How to mock a dependency of a class which is instantiated on runtime [duplicate]

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

Do I need a tear down method when mocking in Mockito?

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

Testing factory behavior

I am wondering what is the best practice to test factory behavior code. In my case, the factory creates some dependency instances that will be passed to the constructor of the FooBar instance.
public class FooBarFactory {
private Dependency1 dependency1;
private Dependency2Factory factory;
public FooBarFactory(Dependency1 dependency1, Dependency2Factory factory) {
this.dependency1 = dependency1;
this.factory = factory;
 }
public FooBar create() {
return new FooBar(dependency1, factory.create(), new Dependency3());
}
}
The dependencies can be created by some other factories or can be created directly by the factory under test.
To test the factory behavior, what I have to do for now is create some protected getters in FooBar to retrieve the dependencies so I can assert the constructor injection and the dependencies were created correctly.
This is where I am unsure. Adding some getters for the purpose of testing bothers me a little since this it breaks encapsulation. I could also use reflection to retrieve the fields value but I usually consider this bad practice since it is easy to break.
Anyone can provide insights into this problem?
One solution is to mock the FooBar class and verify the constructor invocation through which the instance returned by FooBarFactory#create() was created. Using the JMockit mocking API, such a test would look like:
public class FooBarFactoryTest
{
#Injectable Dependency1 dep1;
#Injectable Dependency2 dep2;
#Cascading #Injectable Dependency2Factory dep2Factory;
#Mocked FooBar mockFooBar;
#Tested factory;
#Test
public void createFooBarWithProperDependencies()
{
assertNotNull(factory.create());
new Verifications() {{ new FooBar(dep1, dep2, (Dependency3) withNotNull()); }};
}
}
I suppose the suggestion that comes to mind would be to in turn inject the FooBarFactory's dependencies as well, so that it takes a Dependency1 and Dependency2Factory as either constructor parameters or as values in setter methods.
As a Unit-Test you should test your unit (class) and just this.
The value created by a factory inside your factory should be tested on its unit-test. For example on your situation, it doesn't make sense to test what dependency2Factory return, because in order to FooBar work, Dependency2Factory should work too (in case it isn't configurable), if it is configurable you can provide your own mock and this would be enough.
And Dependency2Factory should be tested on a separated Unit-Test.
You don't test if the method List.get(int index) works every time you use a list in your implementation right?
How about mocking? Mock every dependency required to run the tested piece of code.
There are a few good mock frameworks like mockito.

Categories