JUnit for final method of abstract class - java

I am having trouble writing a JUnit test. The issue is that there is a final method getMessage() in the following block of code:
if(these_conditions_are_true) {
String message = messageResources.getMessage(CONSTANT_STRING, null, LocaleContextHolder.getLocale());
modelView.getModelMap().addAttribute(INLINE_MSG, message);
return modelView;
}
messsageResources is a ReloadableResourceBundleMessageSource which extends AbstractMessageSource, which is an abstract class.
getMessage() is a final method in AbstractMessageSource.
Here is the condensed version of my Test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({AbstractMessageSource.class, ClassBeingTested.class})
public class ClassBeingTestedTest {
#InjectMocks
ClassBeingTested classBeingTested;
#Mock
ReloadableResourceBundleMessageSource messageResources; //being used by a different test in this class, including in case it matters
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
// Build the mock
this.mockMvc = MockMvcBuilders.standaloneSetup(classBeingTested).build();
}
#Test
public void Method_Being_Tested_Test() {
AbstractMessageSource amsMock = PowerMockito.mock(AbstractMessageSource.class);
Mockito.when(amsMock.getMessage(any(), any(), any())).thenReturn("test01");
ModelAndView mv = classBeingTested.methodBeingTested(itemVO);
ModelAndView mv_Expected = createExpectedMV(); //not really how i'm doing it, but for the sake of simplicity i'll omit it
assertEquals(mv_Expected, mv);
}
}
I'm using PowerMockito since I learned that Mockito can't stub final methods.
The error I get is
No message found under code 'CONSTANT_STRING' for locale 'EN_US'.
It appears that my when...thenReturn isn't actually being used as getMessage() is being called. I've tried adding CALLS_REAL_METHOD to the line where I create the Mock, but that didn't seem to work.
Does anyone know how to stub this out? Am I right to mock AbstractMessageSource, rather than ReloadableResourceBundleMessageSource? Any help would be greatly appreciated!
UPDATE:
I'm still looking for help with this. I'm still running into the issue of not being able to intercept getMessage() actually being called...

Try this
Mockito.when(
amsMock.getMessage(
eq(CONSTANT_STRING),
eq(null),
any(Locale.class))).thenReturn("test01");
Edit: This strategy is terrible,
because you will need to mock the getMessage method for every property that is accessed during your unit test.
What you appear to want is the ability to set a property value for use during your unit tests.
If this is the case,
include a property configuration for your unit tests.
For spring,
you can create a unit test configuration that references the test properties and load it with the SpringRunner.

Related

Is it possible to retrieve value from application.properties without autowiring the class under test?

I have a test class that is annotated with #Spy and #InjectMocks and tested using Mockito. The class under test has a value (url) that is retrieved from the application.properties file. I'd like to test whether this url is being set correctly within the method that uses it. I can do this if I remove the #Spy and #InjectMocks annotations and use #Autowire and #SpringBootTest. However, that breaks other tests that use the spy functionality, so I'm just wondering if there's any way we can keep the spy working and test all our methods inside the same file, maybe without the need to bring in the #SpringBootTest annotation and the autowiring? The workaround we're using for now is to have two files, one that uses the spy and the other that tests the specific method to do with the properties file and that requires the full context to load, but not sure that's the best solution here?
Here is the test with the spy:
#ExtendWith(MockitoExtension.class)
class ProviderHelperServiceTest {
#Spy
#InjectMocks
ProviderHelperService providerHelperService;
#Value("${viaduct-url}")
String viaductUrl;
#Test
void testGetRequestBodyUriSpec() {
WebClient.RequestBodyUriSpec requestBodyUriSpec = providerHelperService.getRequestBodyUriSpec("sifToken");
final String[] url = new String[1];
requestBodyUriSpec.attributes(httpHeaders -> {
url[0] = (String) httpHeaders.get("org.springframework.web.reactive.function.client.WebClient.uriTemplate");
});
// Fails as url[0] comes back as null. Disabled and moved to another file.
assertEquals(viaductUrl, url[0]);
}
#SpringBootTest
class ProviderHelperService2Test {
#Autowired
ProviderHelperService providerHelperService;
#Value("${viaduct-url}")
String viaductUrl;
#Test
void testGetRequestBodyUriSpec() {
WebClient.RequestBodyUriSpec requestBodyUriSpec = providerHelperService.getRequestBodyUriSpec("sifToken");
final String[] url = new String[1];
requestBodyUriSpec.attributes(httpHeaders -> {
url[0] = (String) httpHeaders.get("org.springframework.web.reactive.function.client.WebClient.uriTemplate");
});
assertEquals(viaductUrl, url[0]);
}
}
And here is the method under test:
public class ProviderHelperService {
#Value("${viaduct-url}")
String viaductUrl;
public WebClient.RequestBodyUriSpec getRequestBodyUriSpec(String sifToken) {
WebClient.RequestBodyUriSpec requestBodyUriSpec = WebClient.create().post();
requestBodyUriSpec.header("Authorization", sifToken);
requestBodyUriSpec.uri(viaductUrl);
return requestBodyUriSpec;
}
}
The cleanest way to perform such tests is to replace field injection with constructor injection, and then you can quite easily confirm that the value that's passed into the class comes back out the service call.
If you're using Boot, it's usually best to replace use of #Value with #ConfigurationProperties. Depending on the specifics, you can either pass the whole properties object to the service's constructor or write an #Bean configuration method that unpacks the relevant properties and passes them as plain constructor parameters with new.

About #InjectMocks and #Mock

I want to test requestListServiceImpl this class.It contains requestListDao.
RequestListServiceImpl Code
#Override
public PageInfo<RequestList> getAllRequest(int startPage, int pageSize, String accountName,String userName) {
PageHelper.startPage(startPage, pageSize);
List<RequestList> list=requestListDao.getAllRequest(accountName,userName);
for(RequestList requestList:list) {
switch (requestList.getStatus()) {
case "0":
requestList.setStatus("Waiting");
break;
case "1":
requestList.setStatus("Closed");
break;
case "2":
requestList.setStatus("Cancel");
break;
default:
requestList.setStatus("NAN");
break;
}
}
PageInfo<RequestList> pageInfo = new PageInfo<RequestList>(list);
return pageInfo;
}
#Override
public void createRequest(RequestList requestList) {
Integer coount=requestListDao.getTime(requestList.getCreateName());
// AWSSnsUtil.sendMassageToSns(requestList.getAccountName());
requestList.setTime(++coount);
requestListDao.createRequest(requestList);
}
Test Code:
#InjectMocks
RequestListServiceImpl requestListServiceImpl;
#Mock
RequestListDao requestListDao;
#Before
public void setup(){
MockitoAnnotations.openMocks(this);
}
#Test //it's ok
public void testGetAllRequest() throws Exception {
RequestList r=new RequestList();
r.setStatus("0");
when(requestListDao.getAllRequest(anyString(), anyString())).thenReturn(Arrays.<RequestList>asList(r));
PageInfo<RequestList> res=requestListServiceImpl.getAllRequest(1,1,"1","1");
Assert.assertNotNull(res);
}
#Test //this test is error, the error is requestListServiceImpl is not mock.
public void testCreateRequest() throws Exception {
when(requestListDao.getTime(anyString())).thenReturn(0);
RequestList r=new RequestList();
r.setCreateName("demo");
requestListServiceImpl.createRequest(r);
verify(requestListServiceImpl).createRequest(r);
}
Error info
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type RequestListServiceImpl and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
When i change #InjectMocks to #Mock, The second test it's ok ,but first test it's error.
I need add to a stubbing when(requestListServiceImpl.getAllRequest(anyInt(),anyInt(),anyString(),anyString())).thenReturn(new PageInfo<>());
I don't know how to do it,
Is injectmocks necessary?
Here:
verify(requestListServiceImpl)
And
#InjectMocks
RequestListServiceImpl requestListServiceImpl;
The message is pretty clear: you verify mock objects that Mockito created for you.
#InjectMocks does not create mocks. It rather injects mocks that you have in your test class into a real object.
So, what is necessary here: read the manual or a tutorial. Meaning: don't start with Mockito by applying it immediately to your project. Instead, step back, and look at simple examples to understand how it is supposed to be used.
In your current setup: requestListServiceImpl is a real object. So you should check if that class offers you methods to verify its internal status. You triggered some action on it, but because it is a real object, Mockito doesn't know what you did. But how to actually solve this depends on YOUR code base.
You want to test requestListServiceImpl you should use #InjectMocks so mockito calls the real method on requestListServiceImpl. When you use #Mock, the method will by default not be invoked.
#InjectMocks will be the same as if you create it yourself with new requestListServiceImpl(mock(requestListDao))
When you use verify(mock).someMethod(); you have to pass a mock to that method, not #InjectMocks.
You want to verify if a certain method is called on a mock inside your class under test(requestListServiceImpl).
Instead of #InjectMocks there is also #Spy, which will kinda do both, you can mock methods in requestListServiceImpl but also call the real method.

Mockito NotaMockException

I am facing an issue with Mockito junit testing. I am new to it and am a bit confused with the problem I am facing. Any help on this would be appreciated.
class Activity{
public void firstMethod(){
String str = secondMethod();
}
public String secondMethod(){
String str = null;
/* some Code */
return str;
}
}
Getting exception :
*org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!*
in the below code
class ActivityTest(){
Activity act;
#Before
public void setup(){
act = new Activity();
}
#Test
public void testFirstMethod(){
Mockito.doReturn(Mockito.anyString()).when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
I am aware that activity is not a mock but I am not sure for a way around this as secondMethod() is a method in the same class. I need to write rule for secondMethod() as I have already done its Unit Testing. The definition of secondMethod() consists has external dependencies. Should I be mocking the external dependencies present in secondMethod() and writing rules for them rather than rule for secondMethod()?
I found this post:
Mockito Spy'ing on the object being unit tested
However separating the secondMethod() into a different class does not make sense. My method is related to this class. Creating a different class for testing does not seem right to me. Even mocking the actual class using spy() is not the most correct way as already explained in the post.
I don't think I should be creating a mock of the Activity class as that is the class I am testing. I would really appreciate help and insights into this.
As you noted, act is not a mock, and therefore you cannot record behavior on it. You could use Mockito.spy to, well, spy (or partially mock) the act object so that you only record the behavior of secondMethod and execute the actual code for firstMethod.
Note, however, that matchers can't be used in doReturn calls regardles of how you're mocking or spying your object. A return value must be a concrete object.
class ActivityTest() {
Activity act;
#Before
public void setup(){
act = Mockito.spy(new Activity()); // Here!
}
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
A slightly more elegant syntax allows you to use annotations instead of explicitly calling Mockito.spy, but it's a matter of taste really:
#RunWith(MockitoJUnitRunner.class)
class ActivityTest() {
#Spy
Activity act = new Activity();
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
There is no reason to mock anything in this example. Since there are no dependencies and both methods are public, you can test them directly.
public class ActivityTest() {
private Activity act = new Activity();
#Test
public void testSecondMethod(){
assertEquals("expected-value", act.secondMethod());
}
#Test
public void testFirstMethod() {
act.firstMethod();
// success if no exception occurs
}
}
Since firstMethod does not have any detectable effect on the Act instance, nor on any dependency (since there are none) you can simply call the method and be satisfied if no exception is thrown. One could also reason that such a method should not be tested at all.
I assume the example given is a simplification of a class where calling firstMethod actually does have side effects, who knows...
Here are some hints:
Mock the Activity.
Tweak the behavior of secondMethod with when / then / doReturn
Use doCallRealMethod when firstMethod is invoked.
Hope it helps.

Mockito mock objects returns null

I try to implement some tests for my JSF application and for the mocks I am using mockito. (I also use spring)
#RunWith(MockitoJUnitRunner.class)
public class GeneralConfigServiceImplTest {
private GeneralConfigService generalConfigService;
#Mock
private GeneralConfigDAO generalConfigDAO;
#Mock
private GeneralConfig gen;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
generalConfigService = new GeneralConfigService();
ReflectionTestUtils.setField(generalConfigService, "generalConfigDAO", generalConfigDAO);
}
#Test
public void testAddGeneralConfigCallDAOSuccess() throws DAOException, EntityNullException, IllegalEntityArgumentException, ParseException, EntityPersistException {
gen = createGeneralConfigs("label", "value");
generalConfigService.setInstance(gen);
generalConfigService.persist();
log.info(generalConfigService.getInstance().toString());
}
}
The test succeeds, but when I want to retrieve the instance with the getInstance method. All Parameters which I have set before (via the constructor before) are null.
I am new to mocked objects, so is this behavior normal, or is there a mistake in my code?
It really depends on GeneralConfigService#getInstance() implementation. Also you can simplify your test code a lot if you use #InjectMocks annotation.
When using MockitoJUnitRunner you don't need to initialize mocks and inject your dependencies manually:
#RunWith(MockitoJUnitRunner.class)
public class GeneralConfigServiceImplTest {
#InjectMocks
private GeneralConfigService generalConfigService;
#Mock
private GeneralConfigDAO generalConfigDAO;
#Test
public void testAddGeneralConfigCallDAOSuccess() {
// generalConfigService is already instantiated and populated with dependencies here
...
}
}
My problem here was the incorrect import for Test anotation:
Was
import org.junit.jupiter.api.Test;
Correct
import org.junit.Test;
Don't forget to use
MockitoAnnotations.initMocks(this);
If you are Mocking object through annotation i.e. #Mock Objectname
All method calls to Mockito mocks return null by default. If you want it to return something else you need to tell it to do so via a when statement.
It seems the you are thinking that the following will work... you call setInstance and then expect getInstance to return the value that was passed to setInstance since this is how the DAO would work. If this is what you are attempting, you shouldn't test setInstance by then calling getInstance since getInstance will return whatever you have configured the mock to return and will have no relation to what was passed to setInstance. Instead, use verify to validate that the appropriate method of the DAO was called from the setInstance method.
For example, if GeneralConfigService.setInstance calls GeneralConfigDAO.setInstance then your test should look like this...
#Test
public void testAddGeneralConfigCallDAOSuccess() throws DAOException, EntityNullException, IllegalEntityArgumentException, ParseException, EntityPersistException {
gen = createGeneralConfigs("label", "value");
generalConfigService.setInstance(gen);
generalConfigService.persist();
verify(genConfigDAO).setInstance(sameInstance(gen));
}
Also, if gen is a mock (via #Mock) why are you assigning it to something else via gen = createGeneralConfigs...
This thread is an old one, but I got the same problem with junit5 (v5.8.2) and mockito (mockito-core:jar:4.5.1) and none of the answers here helped me. After a 1.5 hours search I found this article:
https://mincong.io/2020/04/19/mockito-junit5/
which helped me! I used the first solution, so I added
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.28.2</version>
<scope>test</scope>
</dependency>
as new dependency and I annotated my class with the following annotation (and I removed the #RunWith(MockitoJUnitRunner.class) annotation):
#ExtendWith(MockitoExtension.class)
Please find the explanation in the article. I hope this help to others as well!

Mockito, Testing an object that relies on injected dependencies (Spring)?

I'm new to using Mockito and am trying to understand a way to make a unit test of a class that relies on injected dependencies. What I want to do is to create mock objects of the dependencies and make the class that I am testing use those instead of the regular injected dependencies that would be injected by Spring. I have been reading tutorials but am a bit confused on how to do this.
I have one the class I want to test like this:
package org.rd.server.beans;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean1 {
#Autowired
private SubBean1 subBean1;
private String helloString;
public String testReturn () {
subBean1.setSomething("its working");
String something = subBean1.getSomething();
helloString = "Hello...... " + something;
return helloString;
}
Then I have the class that I want to use as a mock object (rather than the regular SubBean1 class, like below:
package org.rd.server.beans.mock;
public class SubBean1Mock {
private String something;
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
}
I just want to try running a simple test like this:
package test.rd.beans;
import org.rd.server.beans.TestBean1;
import junit.framework.*;
public class TestBean1Test extends TestCase
{
private TestBean1 testBean1;
public TestBean1Test(String name)
{
super(name);
}
public void setUp()
{
testBean1 = new TestBean1();
// Somehow inject the mock dependency SubBean1Mock ???
}
public void test1() {
assertEquals(testBean1.testReturn(),"working");
}
}
I figure there must be some fairly simple way to do this but I can't seem to understand the tutorials as I don't have the context yet to understand everything they are doing / explaining. If anyone could shed some light on this I would appreciate it.
If you're using Mockito you create mocks by calling Mockito's static mock method. You can then just pass in the mock to the class you're trying to test. Your setup method would look something like this:
testBean1 = new TestBean1();
SubBean1 subBeanMock = mock(SubBean1.class);
testBean1.setSubBean(subBeanMock);
You can then add the appropriate behavior to your mock objects for whatever you're trying to test with Mockito's static when method, for example:
when(subBeanMock.getSomething()).thenReturn("its working");
In Mockito you aren't really going to create new "mock" implementations, but rather you are going to mock out the methods on the interface of the injected dependency by telling Mockito what to return when the method is called.
I wrote a test of a Spring MVC Controller using Mockito and treated it just like any other java class. I was able to mock out the various other Spring beans I had and inject those using Spring's ReflectionTestUtils to pass in the Mockito based values. I wrote about it in my blog back in February. It has the full source for the test class and most of the source from the controller, so it's probably too long to put the contents here.
http://digitaljoel.nerd-herders.com/2011/02/05/mock-testing-spring-mvc-controller/
I stumbled on this thread while trying to set up some mocks for a slightly more complicated situation and figured I'd share my results for posterity.
My situation was similar in the fact that I needed to mock dependencies, but I also wanted to mock some of the methods on the class I was testing. This was the solution:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps someone down the road as it stumped me for a while.

Categories

Resources