I am learning about integration testing a spring app that communicates with a rest API. I found out from this article that spring test supports two ways to do, what I assume the same thing.
Create a mockserver using MockRestServiceServer
Create a mock object using Mockito
I understand that the former intercepts http request; then returns the objects, while the latter returns the object directly without bothering with any http requests at all.
Since in the end, at least in most cases, we just verify the object retrieved and compare it to the expected result.
So, my Questions; if try to compare:
What are possible trade-offs; if I choose either one of them?
Are there any advantages of choosing one than the other?
For which cases would I prefer one compared to the other (possible
use cases of each)?
Mockito mocks out all internal part of restTemplate and just returns responses to method directly.
MockRestServiceServer lets restTemplate to run all the things before httpClient call.
It means you will test error handling, mapping etc with MockRestServiceServer.
Related
There are many pages on the net, declaring that they describe the creation of integration tests with JerseyTest. Such as:
https://blog.codecentric.de/en/2012/05/writing-lightweight-rest-integration-tests-with-the-jersey-test-framework/
But notice! It is not an integration test really. It mocks the whole service under the API function. So, it is a unit test. And all examples for 'integration' tests that I had found, are such mocking stubs.
And I want to create a really integration test, I want to send a JSON string and get back another JSON string (or HTML). Of course, for that Jersey in coordination with JerseyTest should collaborate somehow to create a request, call my API function, follow it to the DB queries, fulfil them, and return a response that I can assert by parts.
How can I do it? (If it is possible, of course)
I am writing a unit test for filter to log request and response message. Can we create the HttpServletRequest and HttpServletResponse message instead of mock to send as a input to doFilter() method.
Sure, just implement the interface. However, these are large interfaces, so it's a lot of code to maintain instead of the mock.
If your reason to not use a mock is a simple aversion to mocks (good!) note that there's really no difference between manually implementing a "mock" object and letting a framework do it for you; in both cases you're giving your code something different from what the web framework you end up using will use.
The code you're writing is perhaps better tested with integration tests - starting a real web server as part of your test harness and generating real HTTP requests.
If you are trying to solve an issue the mocks are creating for you by manually implementing the interface, here's an example of a custom HttpServletRequest implemented as an extension of the implementation that ships with Jetty:
https://github.com/neo4j/neo4j/blob/3.2/community/server/src/main/java/org/neo4j/server/rest/web/InternalJettyServletRequest.java
I am trying to write a test for an API client that uses Jersey Client to make the requests.
I wanted to fake a certain server response to return a pre-captured json string.
Eg.
client().resource("/recommendations").queryParam("username", karan").get(Recommendation.class)
should return the appropriate class based on a json string I have stored in a file.
How can I fake that? Or would I have to instantiate a fake server to return the actual json, and let the jersey client to do it's work?
Thanks
One popular solution is to use a testing framework like EasyMock or Mockito to create a mock Jersey client which expects specific method calls and returns predefined data (e.g. json). The mock is then injected into the API client in place of the real Jersey client.
In general, you can also avoid the frameworks by creating the mock yourself, i.e. subclassing the client and overriding methods you expect to call, to return predefined data. Then pass your mock into the API client as a constructor argument. Whether or not you justify a framework depends on how much mocking you expect to need, which is determined in part by how many external dependencies you have.
I'm working with the Struts2 framework and would like to unit test the execute method below:
public String execute() {
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
setUserPrincipal(); //fetches attribute from request and stores it in a var
setGroupValue(); //
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
return SUCCESS;
}
As you can see most of the logic is database related. So how would I go about unit testing this functionality? I would like to unit test by mocking a HTTPServletRequest with few request variables inside it.
My questions are:
How can I fake/mock a request variable as if its coming from a browser
Should my unit test be calling the actual DAO and making sure that the data is coming back?
If so, how can I call the DAO from unit test since the DAO is tied to the server since jndi pool settings reside on the application server.
I'd appreciate any book/article that shows how to really accomplish this.
The code you have shown us is not enough to fully answer your question.
Line by line
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
This is the hardest line since it uses static method. We would need to see how ApplicationInitializer works. In ideal world the getApplicationContext() method should return mock of ApplicationContext. This mock in turns should return MyDAO when getBean("MyDAO"). mockito is perfectly capable of handling this, as well as all other mocking frameworks.
setUserPrincipal(); //fetches attribute from request and stores it in a var
Where does the request come from? Is it injected to action class? If so, simply inject mocked request object, e.g. MockHttpServletRequest.
setGroupValue(); //
Same as above? Please provide more details, what this method actually does?
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
Your previously created mock should return something when getReportResults() is called with given arguments.
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
I guess methods below set some field on the action class. Because you have full control over what was returned from mocked getReportResults(), this is not a problem.
return SUCCESS;
You can assert whether SUCCESS was the result of execution.
Now in general
How can I fake/mock a request variable as if its coming from a browser
See above, there is a mock built-in in Spring.
Should my unit test be calling the actual DAO and making sure that the data is coming back?
If your unit test calls real DAO, it is no longer unit test. It is an integration test.
If so, how can I call the DAO from unit test since the DAO is tied to the server since jndi pool settings reside on the application server.
This means you are doing integration testing. In that case you should use in-memory database like h2 so you can still run the test on ci server. You must somehow configure your application to fetch DataSource from different place.
Final note
In essence you should inject mocks of everything to your Struts action class. You can tell mocks to return any value upon calling. Then, after calling execute(), you can verify given methods were called, fields set and result value is correct. Consider splitting this to several tests.
Code review
Struts 2 integrates perfectly with Spring. If you take advantage of that functionality Spring container will automatically inject MyDAO to your action class. The first line becomes obsolete.
This code is hard to unit test because instead of using Spring as intended (i.e. as a dependency injection framework), you use it as a factory. Dependency injection is precisely used to avoid this kind of bean lookup you're doing, which is hard to test. The DAO should be injected into your object. That way, you could inject a mock DAO when unit testing your object.
Also, this logic is not database-related at all. The DAO contains the database-related logic. This action uses the DAO, and the DAO is thus another unit (which should be tested in its own unit test). You should thus inject a mock DAO to unit test this method.
Finally, this method doesn't use HttpServletRequest (at least not directly), so I don't understand why you would need to use a fake request. You could mock the setXxx methods which use the request.
Instead of simply mocking the HTTPServletRequest, how about
mocking an actual automated targeted request to the application
itself? Check out Selenium which lets you do just that.
For testing DAOs (integration testing), you could create your databases in memory using HSQLDB, which will allow you to create / delete objects from your tests, and making sure they are persisted / retrieved properly. The advantage with HSQLDB is that your tests will run much quicker than they will with an actual database. When the time comes to commit your code, you could run the tests against your actual database. Usually, you would setup different run configurations in your IDE to facilitate this.
The easiest way to make your injected daos available to your tests is to let your unit test classes extend AbstractJUnit4SpringContextTests. You could then use the #ContextConfiguration annotation to point to multiple xml application context files, or if you use annotation based configuration, point it to your context file which has the <context:annotation-config /> declaration in it.
This class is simply a request dispatcher. It takes request and response objects, and pass down the work according the request type. Application logic is tested. Mocking has to be avoided. How can I write unit test for this dispatcher without turning the test into integration or system test? How are dispatchers usually tested?
EDIT: I was told to avoid mocking. I don't think I can change that decision.
There should be two parts to the code; the first is the marshalling of data between the web layer and dispatching, the second is dispatching to handlers.
Dispatching can be tested using "plain" unit testing, it's just logic to map arbitrary criteria to handlers.
The marshalling layer requires either mocking, or enough integration to create a web request and watch its routing, what's returned from its handler, etc. HtmlUnit is one solution, there are a ton of others.
Use mocks. Do the unit tests.
If you start picking and chosing which parts to test and what not to test, you might as well not test anything at all.
Then again, you might just name them "Bootstraps" or "Imposter" or some other name and get around the restrictions. Alternative, you might be able to hand-code the mocked objects and get around the restrictions that way.