I have the following code in a Java EE managed bean:
FacesContext context = facesContextProvider.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext();
Where facesContextProvider is a custom class for returning the faces context (useful for mock testing).
I'm wondering how to test this in JUnit using mockito. I am trying a combination of:
FacesContextProvider mockFacesContextProvider = mock(FacesContextProvider.class);
when(mockFacesContextProvider.getCurrentInstance()).thenReturn(mockFacesContext);
// this line is wrong ~> when(mockFacesContext.getExternalContext()).thenReturn((ExternalContext) new MockHttpServletResponse());
How can I inject some sort of mock or custom HttpServletResponse into my external context?
Thanks for the help.
ANSWER
My controller code is wrong. You can work with the ExternalContext to do whatever you need. So in the controller, it should actually be:
FacesContext facesContext = facesContextProvider.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.responseReset();
If you still wanted the response, you could get it from:
HttpResponse response = externalContext.getResponse();
Then the unit test harness would be:
mockFacesContextProvider = mock(FacesContextProvider.class);
mockFacesContext = mock(FacesContext.class);
mockExternalContext = mock(ExternalContext.class);
mockHttpSession = mock(HttpSession.class);
when(mockFacesContextProvider.getCurrentInstance()).thenReturn(mockFacesContext);
when(mockFacesContext.getExternalContext()).thenReturn(mockExternalContext);
when(mockExternalContext.getSession(true)).thenReturn(mockHttpSession);
And then the Unit Test code would be:
verify(mockExternalContext).responseReset();
FacesContextProvider mockFacesContextProvider = mock(FacesContextProvider.class);
HttpServletResponse mockResponse = mock(HttpServletResponse.class);
when(mockFacesContextProvider.getCurrentInstance()).thenReturn(mockFacesContext);
when(mockFacesContext.getExternalContext()).thenReturn(mockResponse);
Related
I am writing an unit test in Spock and trying to stub RestTemplate.postForEntity() but seeing a weird issue where the stubs only works when I add a breakpoint and evaluate the expression. It doesnt work and calls the postForEntity() method when run normally.
Here is my implementation.
Test:
def "AuthTokenRequest"() {
given:
def url = "https://authEndpoint"
def map = new LinkedMultiValueMap<>()
RestTemplate restTemplate = GroovySpy(global: true)
restTemplate.postForEntity(*_) >> new ResponseEntity(new AuthResponse(), HttpStatus.OK)
when:
def responseEntity = client.authTokenRequest(url, map)
then:
responseEntity == response
}
Method making the HTTP request:
public AuthResponse authTokenRequest(String url, MultiValueMap map) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<AuthResponse> responseEntity = restTemplate.postForEntity(url, createAuthEntity(map), AuthResponse.class);
return responseEntity.getBody()?:null
}
When I run this test, I get a java.net.UnknownHostException exception because https://authEndpoint doesnt point anywhere which also proves that postEntity() is not being stubbed.
When I put a breakpoint on ResponseEntity<AuthResponse> responseEntity = restTemplate.postForEntity(url, createAuthEntity(map), AuthResponse.class); and evaluate the expression, I get the stubbed response.
Am I doing this wrong?
I am using Mockito to mock my external service and my method that dealing with the external service look like:
public class ExternalConnector{
public ResponseRaw callExternal(RequestParams request, ResponseRaw responseType){
...my implementation to call external service...
}
}
and I mock my response as follow:
ExternalConnector externalConnector = Mockito.spy(new ExternalConnector());
ResonseRaw myMockResponse = ..... mock the response
RequestParams myParameter = ..... mock the params
doReturn(myMockResponse)//
.when(externalConnector)//
.callExternal(isA(myParameter.getClass()), isA(MyResponse.class));
Till now it worked fine. But if I make another mock for my callExternal method with another RequestParams object, then it will get confused here and does not know which response it should mock, something like :
ResonseRaw myMockResponse = ..... mock the response
RequestParams myParameter = ..... mock the params
doReturn(myMockResponse)//
.when(externalConnector)//
.callExternal(isA(myParameter.getClass()), isA(MyResponse.class));
ResonseRaw myMockResponse2 = ..... mock the response
RequestParams myParameter2 = ..... mock the params
doReturn(myMockResponse2)//
.when(externalConnector)//
.callExternal(isA(myParameter2.getClass()), isA(MyResponse.class));
The problem is that myParameter.getClass() and myParameter2.getClass() both return the same RequestParams class type, and therefore basically the signiture for the mock is the same for both cases.
I tried to change the signiture for my mock from isA to eq, but it still did not work:
doReturn(myMockResponse2)//
.when(externalConnector)//
.callExternal(eq(myParameter), isA(MyResponse.class));
Can anyone help me at this point here? Thank you
While doing some searches on SO I came across this piece of code to extract the "appUrl" from a URL:
public static String getAppUrl(HttpServletRequest request)
{
String requestURL = request.getRequestURL().toString();
String servletPath = request.getServletPath();
return requestURL.substring(0, requestURL.indexOf(servletPath));
}
My question is how does one unit test something like this? The key problem is how to create an instance of HttpServletRequest for unit testing?
Fwiw I tried some googling and most of the responses center around mocking the class. But if I mock the class so that getRequestURL returns what I want it to return (taking an example since mocking essentially overrides some methods to return canned values), then I am not really testing the code at that point. I also tried the httpunit library but that also does not help.
I use mockito and here is the block of code in the test method I use to mock it up:
public class TestLogin {
#Test
public void testGetMethod() throws IOException {
// Mock up HttpSession and insert it into mocked up HttpServletRequest
HttpSession session = mock(HttpSession.class);
given(session.getId()).willReturn("sessionid");
// Mock up HttpServletRequest
HttpServletRequest request = mock(HttpServletRequest.class);
given(request.getSession()).willReturn(session);
given(request.getSession(true)).willReturn(session);
HashMap<String,String[]> params = new HashMap<>();
given(request.getParameterMap()).willReturn(params);
// Mock up HttpServletResponse
HttpServletResponse response = mock(HttpServletResponse.class);
PrintWriter writer = mock(PrintWriter.class);
given(response.getWriter()).willReturn(writer);
.....
Hope that helps, I use this to test methods that require servlet objects to work.
I am trying to unit test a service that has a method requiring a request object.
import org.springframework.web.context.request.RequestContextHolder as RCH
class AddressService {
def update (account, params) {
try {
def request = RCH.requestAttributes.request
// retrieve some info from the request object such as the IP ...
// Implement update logic
} catch (all) {
/* do something with the exception */
}
}
}
How do you mock the request object ?
And by the way, I am using Spock to unit test my classes.
Thank you
This code seems to work for a basic unit test (modified from Robert Fletcher's post here):
void createRequestContextHolder() {
MockHttpServletRequest request = new MockHttpServletRequest()
request.characterEncoding = 'UTF-8'
GrailsWebRequest webRequest = new GrailsWebRequest(request, new MockHttpServletResponse(), ServletContextHolder.servletContext)
request.setAttribute(GrailsApplicationAttributes.WEB_REQUEST, webRequest)
RequestContextHolder.setRequestAttributes(webRequest)
}
It can be added as a function to your standard Grails unit test since the function name does not start with "test"... or you can work the code in some other way.
One simple way to mock these, is to modify the meta class for RequestContextHolder to return a mock when getRequestAttributes() is called.
I wrote up a simple spec for doing this, and was quite surprised when it didn't work! So this turned out to be a quite interesting problem. After some investigation, I found that in this particular case, there are a couple of pitfalls to be aware of.
When you retrieve the request object, RCH.requestAttributes.request, you are doing so via an interface RequestAttributes that does not implement the getRequest() method. This is perfectly fine in groovy if the returned object actually has this property, but won't work when mocking the RequestAttributes interface in spock. So you'll need to mock an interface or a class that actually has this method.
My first attempt at solving 1., was to change the mock type to ServletRequestAttributes, which does have a getRequest() method. However, this method is final. When stubbing a mock with values for a final method, the stubbed values are simply ignored. In this case, null was returned.
Both these problems was easily overcome by creating a custom interface for this test, called MockRequestAttributes, and use this interface for the Mock in the spec.
This resulted in the following code:
import org.springframework.web.context.request.RequestContextHolder
// modified for testing
class AddressService {
def localAddress
def contentType
def update() {
def request = RequestContextHolder.requestAttributes.request
localAddress = request.localAddr
contentType = request.contentType
}
}
import org.springframework.web.context.request.RequestAttributes
import javax.servlet.http.HttpServletRequest
interface MockRequestAttributes extends RequestAttributes {
HttpServletRequest getRequest()
}
import org.springframework.web.context.request.RequestContextHolder
import spock.lang.Specification
import javax.servlet.http.HttpServletRequest
class MockRequestSpec extends Specification {
def "let's mock a request"() {
setup:
def requestAttributesMock = Mock(MockRequestAttributes)
def requestMock = Mock(HttpServletRequest)
RequestContextHolder.metaClass.'static'.getRequestAttributes = {->
requestAttributesMock
}
when:
def service = new AddressService()
def result = service.update()
then:
1 * requestAttributesMock.getRequest() >> requestMock
1 * requestMock.localAddr >> '127.0.0.1'
1 * requestMock.contentType >> 'text/plain'
service.localAddress == '127.0.0.1'
service.contentType == 'text/plain'
cleanup:
RequestContextHolder.metaClass = null
}
}
I want to test a Grails controller which calls a service. I'd like to mock the service. The Service has a method:
JobIF JobServiceIF.getJob(int)
and JobIF has a method:
String JobIF.getTitle()
Here's my controller
def workActivities = {
JobIF job = jobService.getJob(params.id)
[career:job]
}
I understand that I need to mock the service and the job class (there are concrete implementations for both) but I'm struggling to get my head around the Groovy mocking object syntax. How do I mock a job and set the title to something, say "Architect" and then test the code?
So far I have:
void testWorkActivities() {
def controller = new CareersController()
... // Mocking stuff I don't know how to do
controller.params.id = 12
def model = controller.workActivities()
assertEquals "Architect", model["career"].getTitle()
}
You basically have two choices
Use the Groovy mocking classes, i.e. MockFor and StubFor
Use the Grails mock classes by calling the mockFor method of GrailsUnitTestCase. The class returned by this method is an instance of GrailsMock
Personally, I have found the Groovy mock objects to a bit more reliable than the Grails mocks. On occasions, I've found that my Grails mock objects were bypassed, even though I appeared to be setting everything up correctly.
Here's an example of how to use the Groovy mocks:
void testCreateSuccess() {
def controller = new CareersController()
// Create a mock for the JobService implementation class
def mockJobServiceFactory = new MockFor(JobService)
mockJobServiceFactory.demand.getJob {def id ->
// Return the instance of JobIF that is used when the mock is invoked
return new Job(title: "architect")
}
// Set the controller to use the mock service
controller.jobService = mockJobServiceFactory.proxyInstance()
// Do the test
controller.params.id = 12
def model = controller.workActivities()
assertEquals "Architect", model["career"].getTitle()
}
The process is basically the same when using the Grails mocks, but you call the mockFor method of the test class, instead of instantiating MockFor.