This is my mock code for testing end to end:
#RunWith(MockitoJUnitRunner.class)
public class testRest extends Jersey Test{
DAOFactory mockDAOfactory;
RPRestrictionReasonDAO fakeDao;
#Before
public void init() {
mockDAOfactory = mock(DAOFactory.class);
fakeDao = mock(RPRestrictionReasonDAO.class);
}
#Test
public void testServiceWorks() throws Exception {
//Assuming I hav already initialized restrictReasons with a dummy value
when(fakeDao.findAll()).thenReturn(restrictReasons);
when(mockDAOfactory.getRPRestrictionReasonDAO()).thenReturn(fakeDao);
String response = client().resource("http://localhost:9998/")
.path("EmployerDetails/PossibleRestrictions")
.get(String.class);
System.out.println("Response is " + response.toString());
}
}
Whenever I do this, I always get the ACTUAL results in my DB rather than the restrictReasons. I've tried all blogs but nothing seems to help. How I get around this? lemme know If I need to post more code.
Note: I have implemented the methods while extending Jersey Test with Grizzly container.
From what I can tell from your code, you are creating the mocks but not actually using the mocks in your client / server implementation.
For a mock to work, it needs to be used by the underlying implementation, not just created in your test class. In this case, assuming your test is running in the same JVM as the server you are testing against, you need to inject your created mocks into the classes that rely on them.
The other answer by #inkalimeva is attempting to address this issue for you by injecting the mocks into your DAO factory. You may be able to fix the error you are experiencing with that answer by changing the DAOFactory declaration to be the concrete class used instead of the abstract one.
E.g.
#InjectMocks
DAOFactoryImpl mockFactory;
Assuming DAOFactoryImpl is your concrete factory class.
Try this, with injecion of mocks using annotations.
#RunWith(MockitoJUnitRunner.class)
public class testRest extends Jersey Test {
#InjectMocks
DAOFactory mockDAOfactory;
#Mock
RPRestrictionReasonDAO fakeDao;
#Before
public void init()
//Do nothing
//mockDAOfactory = mock(DAOFactory.class);
//fakeDao = mock(RPRestrictionReasonDAO.class);
}
#Test
public void testServiceWorks() throws Exception {
//Assuming I hav already initialized restrictReasons with a dummy value
when(fakeDao.findAll()).thenReturn(restrictReasons);
when(mockDAOfactory.getRPRestrictionReasonDAO()).thenReturn(fakeDao);
String response = client().resource("http://localhost:9998/")
.path("EmployerDetails/PossibleRestrictions")
.get(String.class);
System.out.println("Response is " + response.toString());
}
}
Related
I have a class that I'm trying to test where it creates a new object of type AWSStepFunctions, and I'm trying to mock it to return a mock of the same type. I cannot change this original line of code, I can only add tests, so I was wondering how I could go about mocking it.
The class looks looks this --
Class class{
public Object handleRequest(Object object, Context context) {
AWSStepFunctions client = AWSStepFunctionsClientBuilder.standard().withClientConfiguration(new ClientConfiguration()).build();
client.startExecution(...);
}
}
The testing code looks like this -
public class ClassTest {
#Test
public void testHandlerRequest() {
mockStatic(AWSStepFunctionsClientBuilder.class); //mockStatic() and when() from PowerMockito
AWSStepFunctions awsStepFunctionsMock = mock(AWSStepFunctions.class);
AWSStepFunctionsClientBuilder awsStepFunctionsClientBuilder = mock(AWSStepFunctionsClientBuilder.class);
ClientConfiguration configuration = mock(ClientConfiguration.class);
PowerMockito.whenNew(ClientConfiguration.class).withAnyArguments().thenReturn(awsStepFunctionsMock);
when(awsStepFunctionsClientBuilder.standard()).thenReturn(awsStepFunctionsClientBuilder);
when(awsStepFunctionsClientBuilder.withClientConfiguration()).thenReturn(awsStepFunctionsClientBuilder);
when(awsStepFunctionsClientBuilder.build()).thenReturn(awsStepFunctionsMock);
... more when-thenreturns
}
}
I'm running into errors such as NoSuchMethodError for the clientBuilder's mock.
I tried to use PowerMockito's whenNew to mock the creation of the new object of type AWSStepFunctions - PowerMockito.whenNew(AWSStepFunctions.class).withAnyArguments().thenReturn(awsStepFunctionsMock), but that doesn't seem to work as well. Is there a way to return this mock correctly?
You can directly mock static methods with Mockito and Junit5 without using Powermock.
ClassTest
#Test
void test() throws IOException {
try (MockedStatic<AWSStepFunctionsClientBuilder> awsMock = Mockito.mockStatic(AWSStepFunctionsClientBuilder.class, Mockito.RETURNS_DEEP_STUBS)) {
AWSStepFunctions awsStepFunctionsMock = mock(AWSStepFunctions.class);
// You can mock methods chaining when you specify Mockito.RETURNS_DEEP_STUBS
awsMock.when(() -> AWSStepFunctionsClientBuilder.standard().withClientConfiguration(Mockito.any()).build()).thenReturn(awsStepFunctionsMock);
}
}
You can read this post for more explanation about MockedStatic: https://www.baeldung.com/mockito-mock-static-methods
And this one about Mockito.RETURNS_DEEP_STUBS: https://www.baeldung.com/mockito-fluent-apis
Don't forget to configure Mockito to handle static mock :
test/resources/mockito-extensions/org.mockito.plugins.MockMaker
mock-maker-inline
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.
How I can mock a field variable which is being initialized inline?
class Test {
private Person person = new Person();
...
public void testMethod() {
person.someMethod();
...
}
}
Here I want to mock person.someMethod() while testing the Test.testMethod() method for which I need to mock initialization of person variable. Any clue?
Edit: I'm not allowed to modify Person class.
Mockito comes with a helper class to save you some reflection boiler plate code:
import org.mockito.internal.util.reflection.Whitebox;
//...
#Mock
private Person mockedPerson;
private Test underTest;
// ...
#Test
public void testMethod() {
Whitebox.setInternalState(underTest, "person", mockedPerson);
// ...
}
Update:
Unfortunately the mockito team decided to remove the class in Mockito 2. So you are back to writing your own reflection boilerplate code, use another library (e.g. Apache Commons Lang), or simply pilfer the Whitebox class (it is MIT licensed).
Update 2:
JUnit 5 comes with its own ReflectionSupport and AnnotationSupport classes that might be useful and save you from pulling in yet another library.
In case you use Spring Test try org.springframework.test.util.ReflectionTestUtils
ReflectionTestUtils.setField(testObject, "person", mockedPerson);
Pretty late to the party, but I was struck here and got help from a friend. The thing was not to use PowerMock. This works with the latest version of Mockito.
Mockito comes with this org.mockito.internal.util.reflection.FieldSetter.
What it basically does is helps you modify private fields using reflection.
This is how you use it:
#Mock
private Person mockedPerson;
private Test underTest;
// ...
#Test
public void testMethod() {
FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
// ...
verify(mockedPerson).someMethod();
}
This way you can pass a mock object and then verify it later.
Here is the reference.
I already found the solution to this problem which I forgot to post here.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Test.class })
public class SampleTest {
#Mock
Person person;
#Test
public void testPrintName() throws Exception {
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
Test test= new Test();
test.testMethod();
}
}
Key points to this solution are:
Running my test cases with PowerMockRunner: #RunWith(PowerMockRunner.class)
Instruct Powermock to prepare Test.class for manipulation of private fields: #PrepareForTest({ Test.class })
And finally mock the constructor for Person class:
PowerMockito.mockStatic(Person.class);
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
Following code can be used to initialize mapper in REST client mock. The mapper field is private and needs to be set during unit test setup.
import org.mockito.internal.util.reflection.FieldSetter;
new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
if u are using spring boot test and cant find neither of WhiteBox, FeildSetter; u can simply use org.springframework.test.util.ReflectionTestUtils
this is an example:
import org.springframework.test.util.ReflectionTestUtils;
//...
#Mock
private Person mockedPerson;
private Test underTest;
// ...
#Test
public void testMethod() {
ReflectionTestUtils.setField(underTestObject, "person", mockedPerson);
// ...
}
Using #Jarda's guide you can define this if you need to set the variable the same value for all tests:
#Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}
But beware that setting private values to be different should be handled with care. If they are private are for some reason.
Example, I use it, for example, to change the wait time of a sleep in the unit tests. In real examples I want to sleep for 10 seconds but in unit-test I'm satisfied if it's immediate. In integration tests you should test the real value.
The best way until now, I think that is
org.springframework.test.util.ReflectionTestUtils
Im about to mock the private String mockField in FooService.class inside FooServiceTest.java
FooService.java:
#Value("${url.image.latest}")
private String latestImageUrl;
FooServiceTest.java:
#InjectMocks
FooService service;
#BeforeEach
void setUp() {
ReflectionTestUtils.setField(service, // inject into this object
"latestImageUrl", // assign to this field
"your value here"); // object to be injected
}
commons-lang3
import org.apache.commons.lang3.reflect.FieldUtils;
FieldUtils.writeField(object, fieldName, value, true);
I'm writing a Dropwizard application and using Feign for building client calls to outside services. I have custom encoders and decoders I'm registering with the feign.Builder like so:
this.feignBuilder = Feign.builder()
.contract(new JAXRSContract()) // we want JAX-RS annotations
.encoder(new JacksonEncoder()) // same as what dropwizard is using
.decoder(new CustomDecoder())
.errorDecoder(new CustomErrorDecoder())
.requestInterceptor(new AuthKeyInterceptor(config.getInterceptor()));
I'm writing unit tests for the feign client calls so I can watch how the feign machinery deals with my encoder/decoder overrides and bubbles on exceptions. I'm not interested in writing integration tests with a fake server right now (this is the most common type of test i see people writing for this situation).
This should be straight forward. I want to mock the point at which feign makes the request and have it return my fake response. That means I should mock the call to feign.Client.Default.execute so it returns my fake response when it makes the request a this call site. An example of what that mock looks like:
String responseMessage = "{\"error\":\"bad\",\"desc\":\"blah\"}";
feign.Response feignResponse = FeignFakeResponseHelper.createFakeResponse(404,"Bad Request",responseMessage);
Client.Default mockFeignClient = mock(Client.Default.class);
try {
when(mockFeignClient.execute(any(feign.Request.class),any(Request.Options.class))).thenReturn(feignResponse);
} catch (IOException e) {
assertThat(true).isFalse(); // fail nicely
}
No luck. The Cleint.Default class isn't mocked when I reach the call site for the request in the code. What am I doing wrong?
As mentioned before, Mockito is not powerful enough.
I solved this with a manual mock.
It's easier than it sounds:
MyService.Java
public class MyService{
//My service stuff
private MyFeignClient myFeignClient;
#Inject //this will work only with constructor injection
public MyService(MyFeignClient myFeignClient){
this.MyFeignClient = myFeignClient
}
public void myMethod(){
myFeignClient.remoteMethod(); // We want to mock this method
}
}
MyFeignClient.Java
#FeignClient("target-service")
public interface MyFeignClient{
#RequestMapping(value = "/test" method = RequestMethod.GET)
public void remotemethod();
}
If you want to test the code above while mocking the feignclient, do this:
MyFeignClientMock.java
#Component
public class MyFeignClientMock implements MyFeignClient {
public void remoteMethod(){
System.out.println("Mocked remoteMethod() succesfuly");
}
}
MyServiceTest.java
#RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {
private MyService myService;
#Inject
private MyFeignClientMock myFeignClientMock;
#Before
public void setUp(){
this.myService = new MyService(myFeignClientMock); //inject the mock
}
//Do tests normally here...
}
It turns out Mockito is not powerful enough to do the thing I assumed it could do. The correct solution is to use PowerMockito to mock the constructor so Client.Default returns the mocked instance when it is instantiated in the class that holds that reference.
After a lot of compilation-error pain I got PowerMockito to compile and it seemed like it was going to work. Alas it failed to return my mock and the calls were still going through. I've tried PowerMockito in the past and never got around to using it because of the extra problems it caused. So I'm still of the opinion that it's not super easy to just plug and play.
It's a shame that trying to do something like this is so hard.
Is anyone aware of any examples of testing a Java based Play Framework controller by setting mock objects?
I am using Spring in my Play project so all my controller methods are not static.
Testing the tradional way, Play shows my controller as having static methods and I just cant see a way of how I can inject mocks into my object
Result result = callAction(
controllers.routes.ref.LoginController.authenticate(),
fakeRequest().withFormUrlEncodedBody(TestUtils.SUCCESSFUL_LOGIN_MAP)
);
I have a number of services that need to be called in the LoginController and I would like to set those up as mocks
Any help is greatly appreciated
Thanks
Damien
I was looking for the solution of the same problem. So far the best result I was able to achieve is this:
public class MyObjectControllerTest{
private final MyObjectDAO dao = mock(MyObjectDAO.class);
private final MyObjectController controller = new MyObjectController(dao);
public static FakeApplication fakeApplication;
#BeforeClass
public static void startApp() {
fakeApplication = Helpers.fakeApplication();
Helpers.start(fakeApplication);
}
#AfterClass
public static void stopApp() {
Helpers.stop(fakeApplication);
}
#Test(expected = NotFoundException.class)
public void testFailWithUnknownMyObjectKey() throws Throwable {
when(dao.getByKey(any(UUID.class), any(UUID.class), any(Boolean.class))).thenReturn(null);
controller.get(CassandraUUIDs.timeBased());
}
#Test
public void testGetSuccess(){
MyObject deletedObject = MyObjectTestGenerator.generateMyObject();
deletedObject.setDeleted(true);
when(dao.getByKey(any(UUID.class), any(UUID.class), any(Boolean.class))).thenReturn(deletedObject);
try {
Result result = controller.get(CassandraUUIDs.timeBased());
assertThat(status(result)).isEqualTo(Http.Status.GONE);
assertThat(contentType(result)).isEqualTo(Http.MimeTypes.JSON);
assertThat(contentAsString(result)).isEqualTo(ErrorMsg.OBJECT_DELETED.toJson().toString());
} catch (MyObjectsException e) {
e.printStackTrace();
fail("Failed to send MyObject.get request.");
}
}
}
What I do here is instantiate an instance of the controller class and pass mocked DAO instance. Please note that I don't use static controller methods in my code as well.
One issue with this workaround I found so far is that Action (I have custom one) is not working. But Action can (and probably must) be tested separately.