Mockito - Spring unit tests - spring

I've been learning more about the Mockito framework within Java and I'm lost about what to do to complete this unit test.
Basically, the error from the console states that there is a NullPointerException when the Bar.sayHi() method is trying to be run from the Foo test. I suspect it has something to do with the autowired fields (but I maybe wrong)?
Below is a simple example of the problem that I'm running into:
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Mock
//#Spy // Cannot spy on an interface
IBar bar;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
// Given
FooImpl foo = new FooImpl();
foo.saySaySay();
// When
// Then
}
}
Here's the FooImpl class under testing (there's an interface for Foo):
public class FooImpl implements IFoo {
#Autowired
private IBar bar;
public void saySaySay() {
bar.sayHi();
}
}
And the Bar class (there's also an interface for Bar):
public class BarImpl implements IBar {
#Override
public void sayHi() {
System.out.println("hello");
}
}
Does anyone has a suggestion on this? Thanks.

Just creating a mock of Ibar will not inject that mock into the #Autowired field.
Autowiring is the job of Spring, not Mockito.
You need to explicitly tell mockito to inject those into testing objects using #InjectMock
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#InjectMocks
FooImpl foo;
#Mock
IBar bar;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
foo.saySaySay();
}
}
or manual set the mock object inside the tested object.
#Test
public void test() {
FooImpl foo = new FooImpl();
ReflectionTestUtils.setField(foo, "bar", bar);
foo.saySaySay();
}

RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Mock
//#Spy // Cannot spy on an interface
IBar bar;
#InjectMocks
private FooImpl foo;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
// Given
foo.saySaySay();
verify(bar).sayHi();
// When
// Then
}
}

Related

How to mock a ObjectProvider<XXX> that is autowired?

I am doing a migration from Spring 4.x to 5.x and am following the recommendation to wrap the object with an ObjectProvider to handle beans that return null: https://stackoverflow.com/a/49393682/10863988
This is the class set up I have:
class ConfigurationClass{
#Autowired
private ObjectProvider<MyObject> myObject;
public SomeOtherClass getSomeOtherClass() {
return new SomeOtherClass(myObject.getIfAvailable());
}
}
class TestSomeOtherClass {
#Mock
MyObject myObject;
#InjectMocks
ConfigurationClass;
SomeOtherClass someOtherClass;
public void setup() {
this.someOtherClass = spy(configuration.getSomeOtherClass());
}
}
The problem is when I run this test. the myObject in the ConfigurationClass returns a null pointer exception.
I've tried adding this to the TestSomeOtherClass but I still can't seem to mock the ObjectProvider<MyObject>:
class TestSomeOtherClass {
#Mock
MyObject myObject;
#Mock
ObjectProvider<MyObject> myObjectObjectProvider;
#InjectMocks
ConfigurationClass;
SomeOtherClass someOtherClass;
public void setup() {
doReturn(myObject).when(myObjectObjectProvider).getIfAvailable();
this.someOtherClass = spy(configuration.getSomeOtherClass());
}
}
Any advice on how to handle this?
You do not tell Mockito to handle it's annotations (#Mock, #InjectMocks) anywhere in your code, so they do not have any effect. By default all non-primitive fields in Java are initialized as null - that's where the NullPointerException comes from.
openMocks/initMocks method
Depending on the version of Mockito you're using, you need to call initMocks() or openMocks() static method from the MockitoAnnotations class:
AutoCloseable openMocks;
#BeforeEach
public void setup() {
// the line below is where the magic happens
openMocks = MockitoAnnotations.openMocks(this);
doReturn(myObject).when(myObjectObjectProvider)
.getIfAvailable();
someOtherClass = spy(configuration.getSomeOtherClass());
}
#AfterEach
void tearDown() throws Exception {
openMocks.close();
}
#Test
void test() {
assertNotNull(someOtherClass);
}
#ExtendWith(MockitoExtension.class)
You can also use the #ExtendWith(MockitoExtension.class) annotation over your class and it has the same effect as the methods described above.
You can find both approaches tested in a GitHub repository I've created (all tests pass).

Verifying pointcuts being called in tests

I have a dummy project where I try figure out how to test pointcuts being triggered.
My project consists of 1 aspect bean which just prints after a foo method is called
#Component
#Aspect
public class SystemArchitecture {
#After("execution(* foo(..))")
public void after() {
System.out.println("#After");
}
}
And a FooServiceImpl with implemented foo method
#Service
public class FooServiceImpl implements FooService{
#Override
public FooDto foo(String msg) {
return new FooDto(msg);
}
}
The code works and and I can see "#After" being printed to console, but I can't check programatically if after pointcut was called using the test below.
#SpringBootTest
public class AspectTest {
#Autowired
private FooService fooService;
#Test
void shouldPass() {
fooService.foo("hello");
}
}
I've also tried using non-bean proxy as was adviced in https://stackoverflow.com/a/56312984/18224588, but this time I'm getting an obvious error cannot extend concrete aspect because my spy proxy is no longer viewed as an aspect:
public class AspectNoContextTest {
#Test
void shouldPass() {
FooService fooService = Mockito.mock(FooService.class);
SystemArchitecture systemArchitecture = Mockito.spy(new SystemArchitecture());
AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(fooService);
aspectJProxyFactory.addAspect(systemArchitecture);
DefaultAopProxyFactory proxyFactory = new DefaultAopProxyFactory();
AopProxy aopProxy = proxyFactory.createAopProxy(aspectJProxyFactory);
FooService proxy = (FooService) aopProxy.getProxy();
proxy.foo("foo");
verify(systemArchitecture, times(1)).after();
}
}
Ok, after some digging, I found that it's possible to accomplish this by making an aspect a #SpyBean. Also AopUtils can be used for performing additional checks
#SpringBootTest
public class AspectTest {
#Autowired
private FooService fooService;
#SpyBean
private SystemArchitecture systemArchitecture;
#Test
void shouldPass() {
assertTrue(AopUtils.isAopProxy(fooService));
assertTrue(AopUtils.isCglibProxy(fooService));
fooService.foo("foo");
verify(systemArchitecture, times(1)).after();
}
}

When I call method from Test I have Always null resolte

I have test class ExecuteTest and I want to test the method returnString method who is in MyStringClass, and in returnString I call strings() from class OtherString.
This is my code:
#RunWith(MockitoJUnitRunner.class)
public class ExecuteTest {
#InjectMocks
private MyStringClass myStringClass;
#Mock
private OtherString otherString;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testString() {
String test = myStringClass.returnString("test");
assertThat(test, equalTo(test));
}
}
#Service
public class MyStringClass {
#Autowired
private OtherString otherString;
public <T extends Object> T returnString(String key) {
return (T) otherString.strings(key);
}
}
And my test variable is always null in my test.

autowired #components null in unit test

I have a class:
#Component
public class B {
#Autowired
private A a;
}
and A is a component:
#Component
public class A{}
In unit test class BTest:
public class BTest {
#Test
public void testBMethod() {
}
}
I am not using an xml to define context or for beans to be picked from.
What is the cleanest way I can get the test to run?
You don't have to use Spring for the unit tests. Mockito may be used for this.
public class BTest {
#Mock
private A a;
#Mock
private B b;
#Test
public void testBMethod() {
}
}
For more details, you may check https://springframework.guru/mocking-unit-tests-mockito/
and https://dzone.com/articles/use-mockito-mock-autowired

How to inject a bean in a ConstraintValidator with MockMVC?

I have a custom ConstraintValidator:
#Component
public class FooValidator implements ConstraintValidator<FooAnnotation, String> {
#Inject
private FooRepository fooRepository;
#Override
public void initialize(FooAnnotation foo) {
}
#Override
public boolean isValid(String code, ConstraintValidatorContext context) {
Foo foo = fooRepository.findByCode(code);
//My code
}
}
In my Junit tests and MockMVC I call the url but fooRepository bean validator is always null.
How I can inject it in my test controller? I tried to create a mock repository but it is also null.
My source code test:
public class FooControllerTest {
#InjectMocks
private FooController fooController;
private MockMvc mockMvc;
#Before
public void setup() {
// Process mock annotations
MockitoAnnotations.initMocks(this);
// Setup Spring test in standalone mode
this.mockMvc = MockMvcBuilders.standaloneSetup(fooController)
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
.build();
}
#Test
public void testSave() throws Exception {
Foo foo = new Foo();
// given
//My code...
// when
// then
// with errors
this.mockMvc.perform(post("/foo/update")
.param("name", "asdfasd")
.sessionAttr("foo", foo))
.andExpect(model().hasErrors())
.andExpect(model().attributeHasFieldErrors("foo", "name"));
}
}
You should add a #ContextConfiguration to your test, among other things.

Resources