I've a TestClass with two Tests foo() and bar(), foo uses the original bean serviceObject, while bar uses a mockedBean: so always one test fails. is there any way to mock my bean only for bar()
#RunWith(SpringRunner.class)
#SpringBootTest
pubic class TestClass{
#MockBean
private ServiceObject serviceObject;
#Test
public void foo(){
//do smt test with non mocked bean serviceObject
}
#Test
public void bar(){
//do smt with mockedBean
}
}
I would split up the tests into two different classes, as they obviously test something completely different.
One (foo()) probably tests the behaviour of the ServiceBean implementation, the other (bar()) tests something that uses a ServiceBean instance.
I assume you can create one instance with #Autowired annotation in class scope and mock it in method scope.
Just use the object that you need to use in any given test.
Here is some example code:
#RunWith(SpringRunner.class)
#SpringBootTest
public class TestClass {
#MockBean
private ServiceObject mockServiceObject;
#Test
public void foo(){
ServiceObject blam = new ServiceObject();
// Use blam in this test
// do something test with non mocked bean serviceObject
}
#Test
public void bar(){
// do something with mockedBean
// use mockServiceObject in this test
}
}
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.
I am a beginner in Spring and I need to write test for this class if it calls methods:
class ClassOne {
#Autowired
AutowiredClass a1;
#Autowired
AutowiredClass a2;
void methodOne() {
a1.method1();
}
void methodTwo() {
a2.method2();
}
}
I've tried to write test, but failed, got NPE:
class ClassOneTest {
#Autowired
ClassOneInterface c1i;
#Test
public void testMethod1() {
c1i.methodOne(); // <- NPE appears here..
Mockito.verify(ClassOne.class, Mockito.times(1));
}
}
Would be great to successfully test void methods.
You can verify that using a unit test:
#RunWith(MockitoJUnitRunner.class)
public class MyLauncherTest {
#InjectMocks
private ClassOne c1 = new ClassOne();
#Mock
private AutowiredClass a1;
#Mock
private AutowiredClass a2;
#Test
public void methodOne() {
c1.methodOne(); // call the not mocked method
Mockito.verify(a1).method1(); //verify if the a1.method() is called inside the methodOne
}
}
ClassOne defines a spring bean. In order to Autowire the bean's fields you need a Spring Context.
If you want to test ClassOne as a SPRING BEAN, then you need to use SpringTest.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({MyConfig.class}) // Spring context config class
class ClassOneTest {
#Autowired
ClassOneInterface c1i;
...
}
A ClassOne bean will be injected into the test suite c1i field.
Then you can spy on the field using mockito:
ClassOne cSpy = spy(c1i);
Then you can verify method calls on it :
verify(cSpy).someMethod(someParam);
Hope this helps
You are getting a NPE because the loaded context on your test case cannot find the autowired bean you mentioned. You should annotate the test class like so:
#RunWith(SpringRunner.class)
#SpringBootTest
class ClassOneTest {
#Autowired
ClassOneInterface c1i;
#Test
public void testMethod1() {
c1i.methodOne(); // <- NPE appears here..
Mockito.verify(ClassOne.class, Mockito.times(1));
}
}
Consider taking a look at: Similar NPE test error
I want to write a kind of an integration test of a class and the "lower" classes that it calls during operation. I want to mock the database connection that is called by the "lower" class, but I have not found a way to do this.
I have a class, that calls another class, that calls the database through jdbcTemplate. I want to inject a mock jdbcTemplate to the lower class, but I seem to be injecting it to a wrong instance of the class. The code follows this template:
#Component
public class A {
#AutoWired
B b
public String someMethod() {
b.otherMethod();
}
}
#Component
public class B {
#AutoWired
jdbcTemplate jdbctemplate
public String otherMethod() {
jdbctemplate.query(args);
}
}
The test is like follows:
#RunWith(MockitoJUnitRunner.Silent.class)
public class aTestClass {
#Mock
JdbcTemplate jdbcTemplate;
#InjectMocks
B b;
#InjectMocks
A a;
#Test
public void aTest() {
a.someMethod();
}
}
But when I run this test I get a NullPointerException at a.someMethod() - it seems that the B-object being called is null.
The problem is, that if I mock B, then it's not ever going to actually call jdbcTemplate since it is a mock.
Can anybody shed some light on how I could inject a mock jdbcTemplate to a B-object that is being called by A?
If you want an actual integration test:
1) Don't mock the template.. mock the entire repository.
2) You don't need #InjectMocks in an integration test. Spring does the DI.
3) As this is IT test you would need to use SpringRunner.class, not the MockitoJUnitRunner.class runner.
#RunWith(SpringRunner.class)
public class aTestClass {
#MockBean
B b;
#Autowired
A a;
#Test
public void aTest() {
a.someMethod();
}
}
For a unit test just mock the B and inject on A:
#RunWith(MockitoJUnitRunner.Silent.class)
public class aTestClass {
#Mock
B b;
#InjectMocks
A a;
#Test
public void aTest() {
a.someMethod();
}
}
Do not mock dependencies of dependencies in a unit test. You should not care about lower levels there.
After DuckDuckGoing a bit I managed to get the test working with Maciejs instruction. At first it did not work, but adding #Configuration to both the beans it did. Here is the code that worked for me:
#RunWith(SpringRunner.class)
public class aTestClass {
#MockBean
JdbcTemplate jdbcTemplate;
#Autowired
B b;
#Autowired
A a;
#Test
public void aTest() {
when(jdbcTemplate.query(args)).thenAnswer(whatyouwant));
a.someMethod();
}
#Configuration
#Import(A.class)
static class AConfig {
}
#Configuration
#Import(B.class)
static class BConfig {
}
}
Im not new to mockito, but this time I found an interesting case during my work. I hope you can help me out with it.
I need to inject mock to change certain method behaviour during the test. The problem is, the bean structure is nested, and this bean is inside other beans, not accessible from test method. My code looks like this:
#Component
class TestedService {
#Autowired
NestedService nestedService;
}
#Component
class NestedService {
#Autowired
MoreNestedService moreNestedService;
}
#Component
class MoreNestedService {
#Autowired
NestedDao nestedDao;
}
#Component
class NestedDao {
public int method(){
//typical dao method, details omitted
};
}
So in my test I would like the call NestedDao.method to return mocked answer.
class Test {
#Mock
NestedDao nestedDao;
#InjectMocks
TestedService testedSevice;
#Test
void test() {
Mockito.when(nestedDao.method()).thenReturn(1);
//data preparation omitted
testedSevice.callNestedServiceThatCallsNestedDaoMethod();
//assertions omitted
}
}
I have tried to do a initMocks:
#BeforeMethod
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
Also to add annotation upon my test class:
#RunWith(MockitoJUnitRunner.class)
Always getting nullpointers or wrong answer from method (not mocked).
I guess it's this nested calls fault, making it impossible to mock this Dao.
Also Ive read that #InjectMocks only would work with setters or constructor injection, which im missing (just #Autowire on private fields), but it didn't worked when I tried.
Any guess what am I missing? ;)
You could use #MockBean instead of #Mock and #InjectionMock.
#RunWith(SpringRunner.class)
#SpringBootTest
class Test {
#MockBean
NestedDao nestedDao;
#Autowired
TestedService testedSevice;
#Test
void test() {
Mockito.when(nestedDao.method()).thenReturn(1);
//data preparation omitted
testedSevice.callNestedServiceThatCallsNestedDaoMethod();
//assertions omitted
}
}
It makes sense to me, you are so wrong,
why?
It's because you're testing TestedService and the interaction with NestedService, not with the Dao, the Dao interaction should be verified on the NestedService tests
Look this:
#Component
class TestedService {
#Autowired
NestedService nestedService;
String sayHello(String name){
String result = "hello" + nestedService.toUpperCase(name)
}
}
#Component
class NestedService {
#Autowired
MoreNestedService moreNestedService;
String toUpperCase(String name){
String nameWithDotAtTheEnd = moreNestedService.atDot(name);
return nameWithDotAtTheEnd.toUpperCase();
}
}
On your test:
class Test {
#Mock
NestedService nestedService;
#InjectMocks
TestedService testedSevice;
#Test
void test() {
Mockito.when(nestedService.toUpperCase("rene")).thenReturn("RENE.");
//data preparation omitted
Assert.assertEquals("hello RENE.", testedSevice.sayHello("rene"));
//assertions omitted
}
}
As you can see, you are assuming the dependencies of TestedService are working well, you only need to verify that hello is being added as prefix of the string,
public interface Dummy {
public returnSomething doDummyWork(arg1, agr2);
}
public class A implements Dummy {
#AutoWired
PrintTaskExecutor printTaskExecutor;
public returnSomething doDummyWork(arg1, agr2) {
callingVoidMethod();
return something;
}
public void callingVoidMethod() {
printTaskExecutor.printSomething(arg1, arg2);
}
}
public class testDummy {
#Autowired
Dummy dummyA//this bean is configured in ApplicationContext.xml and it works fine.
#Mock
PrintTaskExecutor printaskExecutor;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
printaskExecutor = Mockito.mock(PrintTaskExecutor.class);
Mockito.doNothing().when(printaskExecutor).printSomething(anyString(), anyString());
}
#Test
Public void testA
{
Dummy.doDummyWork(arg1, arg2);//I m giving actual arguments
//instead of moocking it calls the original method.
Mockito.verify(printaskExecutor, times(1)).printSomething(anyString(), anyString());
}
}
I have an autowired TaskExecutor in the class I m testing and I want to mock it.I have tried this in my code and It calls the actual method instead of do nothing and in the verify it errors out saying no interactions happened. How should I handle this situation?
I try to avoid using Mockito and Bean Containers together in one test. There are solutions for that problem. If you use Spring you should use #RunWith(SpringJUnit4Runner.class). More on this subject: Injecting Mockito mocks into a Spring bean
The clean way: Actually your class testDummy does not test Dummy but A. So you can rewrite your class in following way:
public class testA {
#Mock
PrintTaskExecutor printTaskExecutor;
#InjectMocks
A dummyA;
...
BTW: #Mock together with initMocks(this) and printaskExecutor = Mockito.mock(PrintTaskExecutor.class); do the same, you can skip the latter statement.