How can I use/inject the result of one mock into another?
I think I did it in the wrong way
The int param is always null
I use spy because the method I test is void.
Can I do it using mockito?
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
Utils utils;
#Mock
Custom custom;
#Spy
#InjectMocks
MyService service;
#Test
public void test(){
Mockito.when(utils.get("p")).thenReturn(1); //use result of it in the next mock call
Mockito.when(custom.isValid(1)).thenReturn(true); //custom use 1 here
Mockito.doCallRealMethod().when(service).doIt("p");
service.doIt("p");
Mockito.verify(service,Mockito.times(1)).doIt("p");
}
}
#Service
public class MyService {
Utils utils;
Custom custom;
public MyService(Utils utils) {
this.utils = utils;
}
public void doIt(String value){
int param = utils.get(value);
if(custom.isValid(param)){
//do it
}
}
}
You don't actually need to Spy MyService. You can simplify your test and get it to work:
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
Utils utils;
#InjectMocks
MyService service;
#Test
public void test(){
// Arrange
Mockito.doReturn(1).when(utils.get("p"));
Mockito.when(custom.isValid(1)).thenReturn(true);
// Act
service.doIt("p");
// Assert
Mockito.verify(utils, Mockito.times(1)).get("p");
// You should also confirm that whatever is done in `if(param==1)` is actually done
}
}
You're mocking with wrong parameter, change your test like that:
public class Test {
#Mock
Utils utils;
#InjectMocks
MyService service;
#BeforeEach
void setUp(){
initMocks(this);
}
#Test
public void test(){
Mockito.when(utils.get(any())).thenReturn(1);
service.doIt("p");
Mockito.verify(utils).get(any());
}
}
Instead any() you can put any another variable but it should be the same variable with variable which you call the service
Related
I'm using spring-boot-starter-test 2.2.0 which includes Mockito 3.1.0.
I would like to test this class:
#RestController
public class MyClass {
#Autowired MyAutowired myAutowired;
public int myClassMethod(int i) {
return myAutowired.methodToMock(i);
}
}
Which use this one:
#Service
public class MyAutowired {
public int methodToMock(int i) {
return i;
}
}
In my test I would like to run myClassMethod but with a mocked behavior for methodToMock. Ideally I would like to check if methodToMock was called with the expected argument.
Here is what I tried so far:
#SpringJUnitConfig(Config.class)
#WebAppConfiguration
#ExtendWith(MockitoExtension.class)
class MyClassTest {
#Autowired MyClass myClass;
#Mock
private MyAutowired myAutowired;
#BeforeEach
public void initMocks(){
MockitoAnnotations.initMocks(this);
}
#Test
public void myTest() {
Mockito.when(myAutowired.methodToMock(any()).thenReturn(1);
int shouldBe1ButIs2 = myClass.myClassMethod(2);
}
}
What's wrong with that ? And how to make myClass.myClassMethod(2) return 1 ?
The issue is that your object MyClass is not referring to the right mock instance. The MyAutowired has to injected into MyClass.
You have two options:
Creating a setMyAutowired method in MyClass and pass the MyAutowired instance to it in your test class.
Replacing #Autowired with #InjectMocks annotation on MyClass. In this way, an instance of MyClass will be created and mocks objects which you declared in your test will be injected automatically in it.
I normally use the second option, which is more elegant.
How can I mock a member class in another class which has already been spied by PowerMockito.spy()?
#Component
public class BoxFileDao {
#Autowired
private BoxFileService boxFileService;
public void uploadFile() {
.....
boxFileService.uploadFile(user, credential);
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(BoxFileDao.class)
public class BoxFileDaoTest {
#Test
public void testUploadFile() {
BoxFileDao mock = PowerMockito.spy(new BoxFileDao());
(how do I get the boxFileService from mock?)
mock.uploadFile();
verify(boxFileService).uploadFile(user, credential);
}
}
You can use #InjectMock to inject the mocked boxFileService object in the real boxFileDao object. Your test class can be written something like
#RunWith(PowerMockRunner.class)
public class BoxFileDaoTest {
#Mock
private BoxFileService boxFileService;
#InjectMocks
private BoxFileDao boxFileDao;
#Test
public void testUploadFile() {
boxFileDao.uploadFile();
verify(boxFileService).uploadFile(user, credential);
}
}
First you create your class under test BoxFileDao while injecting the mock for boxFileService into it. Afterwards you can create the spy on it.
For example:
BoxFileDao dao = new BoxFileDao();
dao.boxFileService = Mockito.mock(BoxFileService.class);
BoxFileDao spy = Mockito.spy(dao);
But the question would be why do you even want to do that? Is there a reason to spy on BoxFileDao, your class under test?
I want to replace an autowired class of a service in my spring boot app with a mocked implementation of that class that I created specifically for testing.
I chose to create this mocked implementation because the behaviour of this class is too complicated to mock using mockito as it requires multiple other mocks itself.
I am not able to work out how to inject this mocked implementation into the service.
Here is a minimal example of the situation:
#Service
public class ServiceIWantToTestImpl implements ServiceIWantToTest{
#Autowired
ComplicatedDependency complicatedDependency;
#Override
public void methodUsingDependency(){
String string = complicatedDependency.doSomething();
System.out.println(string);
}
}
public class MockComplicatedDependency implements ComplicatedDepencency{
public MockComplicatedDependency(...){
// Inject other mocked objects into this mock
}
public String doSomthing(){
// This would be a mocked version of this function for testing
return "test";
}
}
#RunWith(MockitoJUnitRunner.class)
public class TestingTheService(){
#InjectMock
private static ServiceIWantToTest serviceIWantToTest = new ServiceIWantToTestImpl();
#Mock
ComplicatedDependency mockComplicatedDependency;
#BeforeClass
public static void init(){
mockComplicatedDependency = new MockComplicatedDependency(...);
}
#Test
public void testAttempt(){
serviceIWantToTest.methodUsingDependency(); // This method calls complicatedDependency.doSomething() which does not run the mocked version in MockComplicatedDependency which I wanted to inject, and would always return null instead of the "test" string I put in this example.
}
}
Do you have to use Mockito annotations to setup dependencies for the class under test?
If that is not the main constraint why not just do the plain simple setup and introduce a constructor or a setter in ServiceIWantToTestImpl class for the ComplicatedDependency field and set the dependency in your test setup directly to whatever impl of ComplicatedDependency you like e.g.:
#Service
public class ServiceIWantToTestImpl implements ServiceIWantToTest {
#Autowired
ComplicatedDependency complicatedDependency;
public ServiceIWantToTestImpl() {
}
public ServiceIWantToTestImpl(ComplicatedDependency complicatedDependency) {
this.complicatedDependency = complicatedDependency;
}
#Override
public void methodUsingDependency(){
String string = complicatedDependency.doSomething();
System.out.println(string);
}
}
public class TestingTheService {
private static ServiceIWantToTestImpl serviceIWantToTest;
#BeforeClass
public static void init(){
serviceIWantToTest = new ServiceIWantToTestImpl(new MockComplicatedDependency());
}
#Test
public void testAttempt() {
serviceIWantToTest.methodUsingDependency();
}
}
That is one way.
To make it work with Mockito, You could to use #Spy instead of #Mock like this:
#RunWith(MockitoJUnitRunner.class)
public class TestingTheService {
#InjectMocks
private static ServiceIWantToTestImpl serviceIWantToTest = new ServiceIWantToTestImpl();
#Spy
private static ComplicatedDependency complicatedDependency = new MockComplicatedDependency();
#BeforeClass
public static void init() {
}
#Test
public void testAttempt() {
serviceIWantToTest.methodUsingDependency();
}
}
Though this is a bit of a hack. I strongly recommend that you read the JavaDoc of the #Spy annotation and make sure it's expected use is what you really need for your test.
I am trying to unit test a method, which has different branches depending upon the value of an object that is created inside it. The below code demonstrates it.
public class AClass {
public void method2() {
//Some code goes here
}
public void method1(BClass bObject) {
C_Class cObject = bObject.someMethodThatReturnsC();
if(cObject != null) {
method2();
method2();
}
}}
Below is the TestClass:
public class AClassTest {
#InjectMocks
AClass AClassSpy;
#Mock
BClass b_objectMock;
#Mock
C_Class c_objectMock;
#BeforeMethod
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
public void method1Test () {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC());
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2).method2();
}
}
However, it always FAILS, since the c_objectMock is always null. What do I do to tell Mockito to not to return a null object?
It works good, just use #Before annotation from junit, not #BeforeMethod, and mark your test method like #Test and remove second bracket from
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC())<-this one;
and add bracket at verify:
verify(AClassSpy, times(2)<-here.method2();
And just take care of your code!
This should work:
public class AClassTest {
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Before
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
Instead of before method you can use annotation #RunWith. It looks clearly:
#RunWith(MockitoJUnitRunner.class)
public class AClassTest {
#Spy
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
You are having this behaviour because you are not mocking property the call to someMethodThatReturnsC.
It should be:
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
I would like to set some common expectations on my timeServiceMock, but it is still null in before method. Any way to make it work without need to call before() in every test?
#RunWith(EasyMockRunner.class)
public class MyTest extends EasyMockSupport {
...#TestSubject and so on
#Mock
private TimeService timeServiceMock;
#Before
public void before() {
System.out.println(this.timeServiceMock);
}
...tests
}
Am I missing something?
It looks like EasyMockRunner only creates and injects mocks in #Test.
so if you want to use it in a #Before, remove the #Mock annotation from TimeService and create the mock yourself in #Before. Then you will have to inject the mock yourself into the #TestSubject.
So something like this:
#RunWith(EasyMockRunner.class)
public class MyTest extends EasyMockSupport {
#TestSubject and so on
Foo testSubject = ...
private TimeService timeServiceMock;
#Before
public void before() {
this.timeServiceMock = createMock(TimeService.class);
...
}
#Test
public void mytest(){
testSubject.setTimeService(timeServiceMock);
...
}
}