Mockito when not resetting between Tests [duplicate] - java

I am seeing behaviour that I believe is a bug. #InjectMocks does not seem to create a new test subject before every test method. Where as #Mock does. In the following example, if Subject.section is final one #Test fails. If its not final both pass. My current workaround is to use #BeforeClass, but this is not ideal.
Subject.java:
package inject_mocks_test;
public class Subject {
private final Section section;
public Subject(Section section) {
this.section = section;
}
public Section getSection() {
return section;
}
}
Section.java:
package inject_mocks_test;
public class Section {}
SubjectTest.java
package inject_mocks_test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
public class SubjectTest {
#Mock
Section section;
#InjectMocks
Subject subject;
#BeforeMethod
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test1() {
assertEquals(section, subject.getSection());
}
#Test
public void test2() {
assertEquals(section, subject.getSection());
}
}
Cheers.

You are using the #InjectMocks for constructor incjection. This will work as long as Mockito finds the field not initalized (null). JUnit is creating a new instance of the test class before each test, so JUnit fans (like me) will never face such problem. TestNg is not creating a new instance of test class. It's keeping the state between test methods, so when MockitoAnnotations.initMocks(this) is called for the second time, Mockito will find subject field already initialized and will try to use field injection. This on the other turn will work until the field is not final.
Is this is a bug? I believe not - rather a natural consequence of the API design.
Some workaround for you would be to add
this.subject = null;
in some #AfterMethod method.

Related

how to do junit test for data base insertion using hibernate

I was trying to do j-unit test for project which insert values into database using hibernate classes. The program is creating tables and inserting values into database. but i am not able to do the j-unit part for the test?
I have attached the java table, but the value that i inserting using the test file is not display when i debugged it?
Sample.java
#Entity
public class Sample {
#Id
private int sid;
private String name;
public void set_sid(int sid)
{
this.sid=sid;
}
public void set_name(String name)
{
this.name=name;
}
public int get_sid()
{
return sid;
}
public String get_name()
{
return name;
}
}
SampleInsert.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleInsert {
private Sample s;
private static SessionFactory sf;
public void insert() {
sf = new Configuration().configure(new File("C:/Users/ns068002/eclipse-workspace/JAXRS-HelloWorld1/src/main/java/com/javacodegeeks/enterprise/rest/jersey/hibernate.cfg.xml")).buildSessionFactory();
Session session = sf.getCurrentSession();
session.beginTransaction();
Sample s=(Sample) session.get(Sample.class, 1);
System.out.println(s+"2");
System.out.println(s.get_name());
session.getTransaction().commit();
}
}
SampleInsertTest.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleTest {
Session session;
SampleInsert st;
#Before
public void setUp() {
session=mock(Session.class);
st=new SampleInsert();
}
#Test
public void test() {
Sample s=new Sample();
s.set_sid(1);
s.set_name("gopal");
Mockito.when(session.get(Sample.class,1)).thenReturn(s);
System.out.println(s+"1");
st.insert();
}
}
Looking at your code, I can not see how you would be able to mock/stub the Session or SessionFactory as neither of these things are "injected" into the class SampleInsert.
By "injected" I mean that the values are not passed into the class in some way, this is usually done using annotation with a framework like Spring, or via constructors.
It should be remembered that we are not testing the thing we are mocking, we are replacing the thing being mocked with a representation that is much simpler in order to test a component that makes use of the thing being mocked.
As an example of how you might use Mockito:
public interface SomethingToMock {
int returnSomeValueFor(int value);
}
public class ToBeTested {
private SomethingToMock session;
public ToBeTested(SomethingToMock session) {
this.session = session;
}
public void methodToTestA(int value) {
returnSomeValueFor(value);
}
public int methodToTestB(int value) {
int i = returnSomeValueFor(value);
return i * i;
}
}
#RunWith(MockitoJUnitRunner.class)
public class SomeTests {
#Mock
private SomethingToMock aMock;
private ToBeTested underTest;
#Before
public void setUp() {
underTest = new ToBeTested(aMock);
}
#Test
public void testOne() {
underTest.MethodToTestA(3);
verify(aMock).returnSomeValueFor(3);
}
#Test
public void testTwo() {
when(aMock.returnSomeValueFor(3)).thenReturn(2);
int r = underTest.methodToTestB(3);
assertEqual(r, 4);
}
}
In the example above we create an interface, this represents the thing to be mocked, we should aim to only mock interfaces and only those we or our team has created.
We then have a class that we need to test that uses the interface ToBeTested we can assume that concrete implementation of the interface are tested elsewhere in the project.
ToBeTested has two methods to test, one that has no return so has no side effects that we can see. The second method does some processing and has a side effect.
We then create a test class to test both methods, we insure it is setup to use Mockito (#RunWith(MockitoJUnitRunner.class) we then setup a mock using #Mock, the final setup step is to ensure our class has the mock "injected" into it, this is done in the setUp() method.
Finally we create two tests the first verifies that the mocked method is called, we don't have to set up a when for this in this case as no value will be returned from the method we are testing, just from the method being mocked I believe Mockito will return the default for an int.
The second test tests that a value is returned, thus we setup a when, when the mocked method is called in the way specified in the when the given value is returned and we can assert that the correct value is returned from the method under test, in this case using assertThat
This is the general layout of testing with Mockito. Effective testing is a huge topic, I would suggest you do some research on the web. The Mockito and JUnit docs are very good, and of course GitHub has many projects using both; one idea might be to look at the Mockito and Unit on Github and look at their testing.
Also the Mockito documentation does a very good job of explaining how, why and when to use mocking: http://static.javadoc.io/org.mockito/mockito-core/2.25.1/org/mockito/Mockito.html
I hope this helps.

Mocking object instantiation with new in Java using PowerMock not working

I am trying to Unit Test a class in Java.
Code for this class: ToBeTested
public class ToBeTested {
private Collaborator collaborator;
public ToBeTested() {
System.out.println("ToBeTested: Constructor");
}
public void start() {
System.out.println("ToBeTested: Start");
collaborator = new Collaborator();
}
}
This class ToBeTested depends on another class, Collaborator.
Code for class: Collaborator
public class Collaborator {
Collaborator() {
System.out.println("Collaborator: Constructor");
}
}
While testing the class ToBeTested, I want to stub instantiation of Collaborator. That's a dependency I want to mock and I don't want it's constructor to be called.
I'm using Junit (v4.12) and PowerMock (v1.6.1).
Code for Test Class: TestToBeTested
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.annotation.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.powermock.api.easymock.PowerMock.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ToBeTested.class, Collaborator.class})
public class TestToBeTested {
#Mock
private Collaborator collaborator;
private ToBeTested toBeTested;
#Before
public void setUp() throws Exception {
collaborator = createMock(Collaborator.class);
expectNew(collaborator.getClass()).andReturn(null);
toBeTested = new ToBeTested();
}
#Test
public void test() {
replayAll();
toBeTested.start();
verifyAll();
}
}
My understanding is that this will mock or stub out Collaborator and it's constructor should not be called. However, when I run the test, I notice that original constructor of Collaborator is called.
Output of test run:
ToBeTested: Constructor
ToBeTested: Start
Collaborator: Constructor
I'm very new to Java and Unit Testing in Java, so I apologize if I'm doing a very fundamental mistake here.
During my quest to find out the root cause, I have referred to following SO questions:
PowerMock's expectNew() isn't mocking a constructor as expected
PowerMock expectNew how to specify the type of the parameters
Not able to mock constructor using PowerMock
https://dzone.com/articles/using-powermock-mock
Thank you very much in advance for help/suggestions/feedback.
One possible reason that it might not be working could be this line:
expectNew(collaborator.getClass()).andReturn(null);
collaborator is a mocked instance which means it's "getClass()" method is going to return Collaborator$CGLIBMockedWithPowermock or something like that -- not the Collaborator class you want it to be. So you might get it to work simply by changing that line to:
expectNew(Collaborator.class).andReturn(null);

Powermock : Mocked method still called

First of all, please know that I've searched SO before asking this question, but I was unable to find a satisfying answer.
I'm using JUnit4 and Powermock 1.5.5 (with mockito 1.9.5)
My problem is the following : in my unit tests, I need to mock a static method in a class I can't modify. I only want to mock one method, and not the whole class, so I went for a spy.
Here's what I have so far :
[...]
import static org.mockito.Matchers.*;
import static org.powermock.api.mockito.PowerMockito.*;
#RunWith(JUnitParamsRunner.class)
#ContextConfiguration(locations={"classpath:applicationContext-test.xml"},
loader=MockWebApplicationContextLoader.class)
#MockWebApplication(name="my-app")
#PrepareForTest(value = {
Role.class
})
public class MyTest {
#Rule
public PowerMockRule powerMockRule = new PowerMockRule();
#Before
public void setUp() throws Exception {
initSpring();
mockRoleServices();
}
private void mockRoleServices() throws Exception {
spy(Role.class);
RoleAnswer roleAnswer = new RoleAnswer(RoleEnum.ADMIN);
when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
.then(roleAnswer);
}
private class RoleAnswer implements Answer<Boolean> {
private RoleEnum roleEnum;
private RoleAnswer(RoleEnum roleEnum) {
this.roleEnum = roleEnum;
}
#Override
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return getRenderRequest().getUserRole() != null &&
getRenderRequest().getUserRole().equals(roleEnum);
}
}
}
Here's the problem : the method Role.hasAdministratorRole() is called instead of being mocked
Here's what I tried so far :
Using mockStatic(Role.class) instead of the spy() method. As expected, all methods are mocked, so I end up getting an NPE before Role.hasAdministratorRole() is called
Doing something like doAnswer(...).when(...). I get a runtime error with powermock telling me my mock is not complete (which actually confirms that something's wrong either with my code or with the lib itself)
Trying to declare the method by its name rather than calling it directly : when(Role.class, "hasAdministratorRole", long.class, long.class, long.class). Same behavior
A bunch of other things I don't recall anymore.
Your help will be greatly appreciated.
Thanks !
EDIT : Thanks to SrikanthLingala's answer, I was able to pinpoint the problem.
This didn't work :
when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
.thenAnswer(roleAnswer);
but this did :
doAnswer(roleAnswer).when(Role.class, "hasSiteAdministratorRole",
anyLong(), anyLong(), anyLong());
So switching then when() and the answer() worked
As I do not have all of your implementations, I setup some dummy implementations and made a similar setup like yours. The below code works fine for me.
import static junit.framework.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(value = {
Role.class
})
public class RoleTest {
#Test
public void mockRoleServices() throws Exception {
PowerMockito.spy(Role.class);
PowerMockito.doAnswer(new RoleAnswer(RoleEnum.ADMIN)).when(Role.class, "hasAdministratorRole", Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
Role.printOut();
assertTrue(Role.hasAdministratorRole(1, 1, 1));
}
private class RoleAnswer implements Answer<Boolean> {
private RoleEnum roleEnum;
private RoleAnswer(RoleEnum roleEnum) {
this.roleEnum = roleEnum;
}
public Boolean answer(InvocationOnMock invocation) throws Throwable {
return true;
}
}
}
Dummy Role class:
public class Role {
public static Boolean hasAdministratorRole(long a, long b, long c) {
System.out.println("Inside hasAdministratorRole");
return a + b + c < 0;
}
public static void printOut() {
System.out.println("Inside Printout");
}
}
My test case does not printout Inside hasAdministratorRole, but prints out Inside Printout
Hope this helps
Glad you have solved your issue, this just a warning for everyone else having a similar issue.
Project setup:
Powermock 1.5.5
Mockito 1.9.5
TestNG 6.8.8
Powermock is not taking into account mocks/spies created in a method annotated with #BeforeTest
E.g.:
#BeforeTest
public void setup(){
testee = mock(AClass.class);
}
It gets discarded and then it is entering the mocked method instead of returning the expected result OR throwing all kinds of strange exceptions. When moved to a common test method, it suddenly starts working:
#Test
public void test(){
AClass testee = mock(AClass.class);
....
}
Possibly it is a bug.

Do Mock objects get reset for each test?

I'm using the Mockito framework to create Mock objects in my JUnit tests. Each mock knows what methods have been called on it, so during my tests I can write
verify(myMock, atLeastOnce()).myMethod();
I am wondering if this internal mock knowledge of what it has called will persist across my tests? If it does persist, then I could be getting false positives when using the same verify method in two tests.
A code example
#RunWith(MockitoJUnitRunner.class)
public class EmrActivitiesImplTest {
#Mock private MyClass myMock;
#Before
public void setup() {
when(myMock.myMethod()).thenReturn("hello");
}
#Test
public void test1() {
// ..some logic
verify(myMock, atLeastOnce()).myMethod();
}
#Test
public void test2() {
// ..some other logic
verify(myMock, atLeastOnce()).myMethod();
}
}
Mock state is persisted - test2 will pass regardless, since test1's verify method passed
Mock state is reset - test2 will fail if myMock.myMethod() isn't called
JUnit creates a new instance of test class each time it runs a new test method and runs #Before method each time it creates a new test class. You can easily test it:
#Before
public void setup() {
System.out.println("setup");
when(myMock.myMethod()).thenReturn("hello");
}
And MockitoJUnitRunner will create a new MyMock mock instance for every test method.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
#RunWith(MockitoJUnitRunner.class)
public class sandbox {
#Mock
private MyClass myMock;
#Before
public void setup() {
when(myMock.myMethod()).thenReturn("hello");
}
#Test
public void test1() {
myMock.myMethod();
verify(myMock, times(1)).myMethod();
}
#Test
public void test2() {
myMock.myMethod();
verify(myMock, times(1)).myMethod();
}
}
This passes. If the state persisted then the second test would fail. If you debug it you would see that you get a new instance of the mocked object for each test.
If you just initialize the Mock objects in your setup, then inside each test you can provide different functionality. You can initialize it once and change how they act/expect per test after that.

passing Parameterized input using Mockitos

I am using Mockito for unit testing. I am wondering if its possible to send Parametrized input parameters with as in Junit testing
e.g
#InjectMocks
MockClass mockClass = new MockClass();
#Test
public void mockTestMethod()
{
mockClass.testMethod(stringInput);
// here I want to pass a list of String inputs
// this is possible in Junit through Parameterized.class..
// wondering if its can be done in Mockito
}
In JUnit, Parameterized tests use a special runner that ensure that the test is instantiated multiple times, so each test method is called multiple times. Mockito is a tool for writing specific unit tests, so there is no built-in ability to run the same test multiple times with different Mockito expectations.
If you want your test conditions to change, your best bet is to do one of the following:
Parameterize your test using JUnit, with a parameter for the mock inputs you want;
Run a loop of different parameters in your test, which unfortunately avoids the "test one thing per method" philosophy
Extract a method that actually performs the test, and create a new #Test method for each mock you want.
Note that there's no prohibition on using mock objects as #Parameterized test parameters. If you're looking to parameterize based on mocks, you can do that, possibly creating the mock and setting the expectations in a static method on the test.
Note about runners: This Parameterized test runner conflicts with Mockito's MockitoJUnitRunner: Each test class can only have one runner. You'll want to switch to #Before and #After methods or a Mockito JUnit4 rule for your setup, if you use them both.
As an example, compressed from a different answer that explains more about Parameterized runners versus JUnit rules and lifting from the JUnit4 Parameterized Test doc page and MockitoRule doc page:
#RunWith(Parameterized.class)
public class YourComponentTest {
#Rule public MockitoRule rule = MockitoJUnit.rule();
#Mock YourDep mockYourDep;
#Parameters public static Collection<Object[]> data() { /* Return the values */ }
public YourComponentTest(Parameter parameter) { /* Save the parameter to a field */ }
#Test public void test() { /* Use the field value in assertions */ }
}
If you are stuck with an older version of mockito where MockitoRule isn't available, the other possibility is to initialize the mocks explicitely with MockitoAnnotations.initMocks:
#RunWith(Parameterized.class)
public class YourComponentTest {
#Mock YourDep mockYourDep;
#Parameter
public Parameter parameter;
#Parameters public static Collection<Object[]> data() { /* Return the values */ }
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test public void test() { /* Use the field value in assertions */ }
}
You can use the JUnitParamsRunner. Here's how I do it:
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.util.Arrays;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
#RunWith(value = JUnitParamsRunner.class)
public class ParameterizedMockitoTest {
#InjectMocks
private SomeService someService;
#Mock
private SomeOtherService someOtherService;
#Before
public void setup() {
initMocks(this);
}
#Test
#Parameters(method = "getParameters")
public void testWithParameters(Boolean parameter, Boolean expected) throws Exception {
when(someOtherService.getSomething()).thenReturn(new Something());
Boolean testObject = someService.getTestObject(parameter);
assertThat(testObject, is(expected));
}
#Test
public void testSomeBasicStuffWithoutParameters() {
int i = 0;
assertThat(i, is(0));
}
public Iterable getParameters() {
return Arrays.asList(new Object[][]{
{Boolean.TRUE, Boolean.TRUE},
{Boolean.FALSE, Boolean.FALSE},
});
}
}
What solved it for me was:
Class level annotation of #ExtendWith(MockitoExtension.class)
Annotate each mock object with #Mock
#InjectMocks on the test class. Or a setup method annotated with #BeforeEach where you initialise the class to be tested.
if you need the #test annotation, make sure you import org.junit.jupiter.api.Test. org.junit.test will not work!
I'm using mockito version 4.

Categories