I am using Springboot with Mockito for test.
I want mock a function that she return a string.
Code impl:
EDIT
public String replaceContent(String url, String replace, String value) {
return url.replace(replace, value);
}
public ResponseEntity<List<MonitorOperativeFront>> getOperativesMonitor(String userCode) {
log.info(" ---> LogInfo: start ");
String url = this.replaceContent(this.urlBase,this.stringReplace,userCode);
log.info(" ---> LogInfo: call to: " + url);
List<MonitorOperativeFront> list= null ;
MonitorOperative[] operative = this.restTemplate.getForObject(url, MonitorOperative[].class);
list.add(new MonitorOperativeFront(operative[0].getId()));
log.info(" ---> LogInfo: Success ");
return new ResponseEntity<>(list, HttpStatus.OK);
}
Code Test:
#Mock
Mockito mk;
#InjectMocks
MonitorServiceImpl monitorService;
#Test
public void testG() throws Exception {
String url = "prueba/test";
this.mk.when( monitorService.replaceContent("prueba/{id}", "{id}", "test"))
.thenReturn(url);
ResponseEntity<List<MonitorOperativeFront>> operative2 = monitorService.getOperativesMonitor("n11111");
assertEquals(true,true);
Err:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
I checked that my function return success "prueba/test" but in mockito I get a error and I don't know resolve...
The #Mock should be the class which has the Method you would like to mock. If you would like to mock the replaceContent you have to write
#Mock
MonitorServiceImpl monitorServiceMock;
#InjectMocks
SomeUserOfMonitorServiceImpl monitorServiceImplUser;
#Test
public void testG() throws Exception {
String url="http://dsgdfgdf/"
Mockito.when( monitorServiceMock.replaceContent("prueba/{id}", "{id}", "test"))
.thenReturn(url));
//Do Something which calls the monitorService.replaceContent
monitorServiceImplUser.doSomething();
Related
I am writing a ParametrizedTest in Junit. The argument for that test is from an enum source.
I want to construct an object with that enum and make the mocked method return that object.
However, when I try to do that, I am getting (what I think is) an irrelevant error message.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here:
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
Here is the code:
public static enum CodeEnum {
S1("S1"),
S2("S2)
}
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Mocked
MockedObject mockedObject;
#InjectMocks
Foo underTest
#ParameterizedTest
#EnumSource(CodeEnum.class)
public void test_ParametrizedTest(CodeEnum enum) {
Output expectedReturn = Output.builder().code(enum).build();
// Given
when(mockedObject.method(any()))
.thenReturn(expectedReturn);
// when
val result = underTest.method();
// then
assertEquas(enum, result.getCode())
}
}
I suspected that the input should be something other than any() so I created a method that provides data to the test and used a #MethodSource annotation.
That method returns the arguments of the input to the mock and also expectedReturn from the mock.
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Mocked
MockedObject mockedObject;
#InjectMocks
Foo underTest
#ParameterizedTest
#MethodSource("dataProvider")
public void test_ParametrizedTest(MockedInput mockedInput, Output expectedReturn) {
Output expectedReturn = Output.builder().code(enum).build();
// Given
when(mockedObject.method(mockedInput))
.thenReturn(expectedReturn);
// when
val result = underTest.method();
// then
assertEquas(enum, result.getCode())
}
private static Stream<Arguments> dataProvider() {
return Stream.of(
Arguments.of(mockedInput1, Output.builder().code(CodeEnum.S1).build()),
Arguments.of(mockedInput2, Output.builder().code(CodeEnum.S2).build())
)
}
}
How to make mocked objects return a parameter from a parametrized test?
The runner I was using was incorrect. I changed it to use MockitoExtension and the tests ran fine.
#ExtendWith(MockitoExtension.class)
public class FooTest {
#Mocked
MockedObject mockedObject;
#InjectMocks
Foo underTest
#ParameterizedTest
#MethodSource("dataProvider")
public void test_ParametrizedTest(MockedInput mockedInput, Output expectedReturn) {
Output expectedReturn = Output.builder().code(enum).build();
// Given
when(mockedObject.method(mockedInput))
.thenReturn(expectedReturn);
// when
val result = underTest.method();
// then
assertEquas(enum, result.getCode())
}
private static Stream<Arguments> dataProvider() {
return Stream.of(
Arguments.of(mockedInput1, Output.builder().code(CodeEnum.S1).build()),
Arguments.of(mockedInput2, Output.builder().code(CodeEnum.S2).build())
)
}
I am trying to test a static method using PowerMock as mentioned its documentation.
However, when I try to verify the following method as shown below, I get "Argument passed to verify() is of type Class and is not a mock!" error. Here is the service method that I am testing and test method:
service:
// I want to test this method
public CommandDTO create(EmployeeRequest request) {
// ...
log();
return CommandDTO.builder().uuid(employee.getUuid()).build();
}
private void log() {
LoggingUtils.info("Created...");
}
test:
#RunWith(PowerMockRunner.class)
#PrepareForTest(LoggingUtils.class)
public class EMployeeServiceImplTest {
#Test
public void unit_test() {
// ...
PowerMockito.mockStatic(LoggingUtils.class);
employeeService.create(request);
PowerMockito.verifyStatic(LoggingUtils.class, Mockito.times(1)); // throws error
LoggingUtils.info(any());
}
}
I'm trying to mock the return value for a method using the when call from mockito. However, I'm new to this and I may perhaps be misunderstanding how mockito works, since the call is failing inside the method mocked when that calls another method. I thought regardless of how that method is implemented, I should be getting the return value I'm asking for? Or do I need to mock also the internals for that method? I feel that shouldn't be it.
public boolean verifyState(HttpServletRequest request, String s) {
String stateToken = getCookieByName(request, STATE_TOKEN);
String authToken = getCookieByName(request, AUTHN);
boolean isValidState = true;
if (isValidState) {
try {
log.info(getEdUserId(stateToken, authToken));
return true;
} catch (Exception e) {
ExceptionLogger.logDetailedError("CookieSessionUtils.verifyState", e);
return false;
}
} else {
return false;
}
}
public String getEdUserId(String stateToken, String authToken) throws Exception {
String edUserId;
Map<String, Object> jwtClaims;
jwtClaims = StateUtils.checkJWT(stateToken, this.stateSharedSecret); // Failing here not generating a proper jwt token
log.info("State Claims: " + jwtClaims);
edUserId = sifAuthorizationService.getEdUserIdFromAuthJWT(authToken);
return edUserId;
}
My test:
#ActiveProfiles(resolver = MyActiveProfileResolver.class)
#WebMvcTest(value = CookieSessionUtils.class, includeFilters = {
#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {ApiOriginFilter.class, ValidationFilter.class})})
class CookieSessionUtilsTest {
#Autowired
private CookieSessionUtils cookieSessionUtils; // Service class
#Mock
private CookieSessionUtils cookieSessionUtilsMocked; // Both the method under test and the one mocked are under the same class, so trying these two annotations together.
#Mock
private HttpServletRequest request;
#BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testVerifyState1() throws Exception {
//...Some mocks for getCookieName
UUID uuid = UUID.randomUUID();
when(cookieSessionUtils.getEdUserId(anyString(), anyString()).thenReturn(eq(String.valueOf(uuid))); // When this line runs it fails on verifyState method
assertTrue(cookieSessionUtils.verifyState(request, ""));
}
UPDATE
Attempt using anyString() instead of eq().
Thank you.
Your test is broken in a few places.
Setting expectations on a real object
You should call Mockito.when on mocks and spies, not on System under test. Mockito normally reports it with a clear error message, but you throw a NPE from getEdUserId, so this is reported instead. The NPE stems from the fact that both eq and anyString return null, which is passed to the real method.
Invalid use of matchers
As #StefanD explained in his answer eq("anyString()") is not matching any string. It matches only one string "anyString()"
Returning a mather instead of real object
thenReturn(eq(String.valueOf(uuid)))
This is illegal position for a matcher.
Mixing Mockito and Spring annotations in a WebMvcTest
This is a common error. Mockito does not inject beans to the spring context.
From the code provided it is unclear what CookieSessionUtils is (Controller? ControllerAdvice?) and what is the correct way to test it.
Update
It seems that you are trying to replace some methods under test. A way to do it is to use a Spy.
See https://towardsdatascience.com/mocking-a-method-in-the-same-test-class-using-mockito-b8f997916109
The test written in this style:
#ExtendWith(MockitoExtension.class)
class CookieSessionUtilsTest {
#Mock
private HttpServletRequest request;
#Mock
private SifAuthorizationService sifAuthorizationService;
#Spy
#InjectMocks
private CookieSessionUtils cookieSessionUtils;
#Test
public void testVerifyState1() throws Exception {
Cookie cookie1 = new Cookie("stateToken", "stateToken");
Cookie cookie2 = new Cookie("Authn", "Authn");
when(request.getCookies()).thenReturn(new Cookie[]{cookie1, cookie2});
UUID uuid = UUID.randomUUID();
doReturn(String.valueOf(uuid)).when(cookieSessionUtils).getEdUserId(anyString(), anyString());
assertTrue(cookieSessionUtils.verifyState(request, ""));
}
}
An alternative way is to call the real method, but to mock all collaborators: StateUtils and sifAuthorizationService. I would probably go with this one, if you want to test public getEdUserId.
Test written when mocking collaborators:
#ExtendWith(MockitoExtension.class)
class CookieSessionUtilsTest {
#Mock
private HttpServletRequest request;
#Mock
private SifAuthorizationService sifAuthorizationService;
#InjectMocks
private CookieSessionUtils cookieSessionUtils;
#Test
public void testVerifyState1() throws Exception {
Cookie cookie1 = new Cookie("stateToken", "stateToken");
Cookie cookie2 = new Cookie("Authn", "Authn");
when(request.getCookies()).thenReturn(new Cookie[]{cookie1, cookie2});
UUID uuid = UUID.randomUUID();
when(sifAuthorizationService.getEdUserIdFromAuthJWT(cookie2.getValue())).thenReturn(String.valueOf(uuid));
assertTrue(cookieSessionUtils.verifyState(request, ""));
}
}
I took the assumption that StateUtils.checkJWT does not need to be mocked
The points above are still valid and need to be resolved in either case.
Remarks
As the system under test is currently a Service, I suggest to drop WebMvcTest and test it with plain mockito instead.
Should SUT be a service? It is more typical to handle auth code in filters.
note usage of doReturn when stubbing a method on a spy.
You use mocks in more places than needed. For example Cookie is trivial to construct, there is no point in using a mock
The error is here:
when(cookieSessionUtils.getEdUserId(eq("anyString()"), eq("anyString()"))).thenReturn(eq(String.valueOf(uuid)));
It should read like
when(cookieSessionUtils.getEdUserId(anyString()), anyString()).thenReturn(uuid);
Please refer to the Mockito documentation of Argument matchers.
Because the argument matchers looking for the string "anyString()" they never match the actual parameters the method call is providing and so there is never returned the uuid you expecting.
I want to check if toDishResponseDTO was called during a method execution. But it's not possible since this is a method of the class being tested. How can this be done?
Class
#ExtendWith(MockitoExtension.class)
class DishServiceTest {
#Mock
DishRepository dishRepository;
#Mock
RestaurantRepository restaurantRepository;
#Autowired
#InjectMocks
DishService dishService;
Method under test
public List<DishResponseDTO> getAll() {
List<Dish> dishlsit = dishRepository.findAll();
return dishlsit.stream()
.map(this::toDishResponseDTO)
.collect(Collectors.toList());
}
Test
#Test
void shouldCallFindAllReturnDto_whenV() {
Mockito.when(dishRepository.findAll()).thenReturn(TestData.ENTITY_DISH);
dishService.getAll();
Mockito.verify(dishRepository, times(1)).findAll();
Mockito.verify(dishService times(6)).toDishResponseDTO(any()); // compile error, because verify can be called only on mocks
}
You won't be able to use Mockito to verify that method is called, but you can verify the output from the getAll() method given that you've mocked out the response to dishRepository.findAll(). So, in effect, just add some assertions after your verify calls that match your expected data with the actual data, I assume that this::toDishResponseDTO just return a Dish.
#Test
void shouldCallFindAllReturnDto_whenV() {
Mockito.when(dishRepository.findAll()).thenReturn(TestData.ENTITY_DISH);
List<Dish> dishes = dishService.getAll();
Mockito.verify(dishRepository, times(1)).findAll();
assertThat(dishes, is(notNullValue());
assertThat(dishes.get(0).getSomeField, is(equalTo("someValue")));
}
Im trying to make a simple as a can example which could be found on official PowerMock's page (here).I' doing a partial mock of this class :
public class Simple {
public String doMe() {
return privateMethod();
}
private String privateMethod() {
return "POWERMOCK sucks";
}
}
And wrote a simple test class :
#RunWith(PowerMockRunner.class)
#PrepareForTest(Simple.class)
public class ProcessorTest {
#Test
public void doMe() throws Exception {
Simple spy = PowerMockito.spy(new Simple());
PowerMockito.doReturn("hello").when(spy, "privateMethod");
String res = spy.doMe();
PowerMockito.verifyPrivate(spy, Mockito.times(1000)).invoke(
"privateMethod");
Assert.assertEquals( res, "hello");
}
}
But result is like this :
java.lang.AssertionError: expected [hello] but found [null]
Expected :hello
Actual :null
<Click to see difference>
at org.testng.Assert.fail(Assert.java:94)
So Powermock not only fails to mock the privateMethod and return 'null' it's OK with that it was called 1000 times when it was not.
It get even more creepy if I try to mess with mocking like this :
PowerMockito.doReturn(1).when(spy, "privateMethod");
So I'm trying to return an Integer instead of String from the privateMethod.
Then I get this :
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Integer cannot be returned by doMe()
doMe() should return String
***
So by some reason Powermock is trying to mock public doMe method.
Any one understands what is happining? I dont.
Thanks.
My environment is :
Java 1.8, Mockito 1.10.19, Powermock 1.6.2
Ok, I found solution, the problem was that JUnit's #RunWith did not actually do the trick so I had to extend from PowerMockTestCase to make it work. The test looks like this now and it works like a charm:
#PrepareForTest(Simple.class)
public class ProcessorTest extends PowerMockTestCase {
#Test
public void doMe() throws Exception {
Simple spy = PowerMockito.spy(new Simple());
PowerMockito.doReturn("hello").when(spy, "privateMethod");
String res = spy.doMe();
PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke(
"privateMethod");
Assert.assertEquals( res, "hello");
}
}