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.
Related
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.
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)
Currently I'm using pact-jvm-consumer/provider-junit_2.11 from au.com.dius lib. Got my consumer pact working and generating pacts, but the problem comes when I try to use these in my provider service.
The idea is to make all pacts integrally with junit tests, so everyone could run their unit tests locally without worrying about additional pact tests.
The main question is:
How to handle this, assuming service under tests requires another service (authorization one) and a db as a data feeder. I'm not quite convinced that each time running these instances locally and than killing them does the trick. (Would like to perform tests before even deploying these to any environments)
Should this be handled with some kind of 'hack-switch' to always return true, as authorized user in 'some circumstances', and mock a data-feeder? Or should it be handled in any other way?
Secondly (the side question):
Once i got my pact ready, how should I test these against a consumer? So far I got things like: (which works just fine, but I'm also not sure about these)
assertThat(result, instanceOf(DataStructure.class)); *as an example*
Above is to make sure that data I've received and pushed to my consumer are in the exact format I've been expecting. Is that ok, or the correct approach is to unpack all of these and check separately if these are e.g. Maps or Strings
Thanks in advance!
Here are some thoughts on stubbing service during verification:
https://github.com/pact-foundation/pact-ruby/wiki/FAQ#should-the-database-or-any-other-part-of-the-provider-be-stubbed
The pact authors' experience with using pacts to test microservices has been that using the set_up hooks to populate the database, and running pact:verify with all the real provider code has worked very well, and gives us full confidence that the end to end scenario will work in the deployed code.
However, if you have a large and complex provider, you might decide to stub some of your application code. You will definitely need to stub calls to downstream systems or to set up error scenarios. Make sure, if you stub, that you don't stub the code that actually parses the request and pulls the expected data out, because otherwise the consumer could be sending absolute rubbish, and the pact:verify won't fail because that code won't get executed. If the validation happens when you insert a record into the datasource, either don't stub anything, or rethink your validation code.
I personally would stub an authentication service (assuming you already have some other tests to show that you're invoking the authentication service correctly) but I generally use the real database, unless this complicates things such that using a mock is "cheaper" (in time, effort, maintainability).
In regards to your second question, I'm not exactly sure what you're talking about, but I think you're talking about making assertions about the properties of the object that has been unmarshalled from the mocked response (in the consumer tests). I would have one test that checked every property, to make sure that I was using the correct property names in my unmarshalling code. But as I said, I would only do this once (or however many times it was required to make sure I had checked every property name once). In the rest of the tests, I would just assert that the correct object class was returned.
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.
I want to write a unit test for a servlet class that makes a call to a web service through java.net.URL.
I can create mock request and response objects to send to the servlet's doGet method easily (using the techniques from the pragmatic programmer text on junit), i.e., creating MockHttpServletRequest, MockHttpServletResponse, and passing these to doGet.
The part I'm having trouble with is the URL open in the servlet.
Right now, i'm just choosing between a call to a function that opens the URL and returns a string (the production code) and a call to a function that returns that directly returns a string for a fixed URL (the test code)
Ideally i'd like to have a doGet method in which the testing code is invisible - the choice between the function that makes the network access, and the one that directly returns a string should be transparent to doGet.
i can think of a number of ways of achieving this, but none feel right.
Example 1: wrap the function in a class that has a testOn boolean, and a setTestMode method; junit init can set the testMode to true, default is false. the testOn decides which method to call. negative is that i need a new class, seems like it could get out of hand.
Example 2: have two classes implementing the network access, one of which is the mock; have junit reload the mock class, production code load the regular class (or somehow remap the production class to the mock class). negative: not sure how this would be done; seems clumsy.
Example 3: have a class with static fields indicating if i want to use mocks, and condition the URL access in the servlet based on the field values. negative: feels like global variables.
Example 4: extend URL, so that the production code will work fine if i switch to URL only (but java.net.URL is final).
I couldn't find quite the right answer through a morning of searches, hence my turning to the collective wisdom of SO.
Thanks,
Adnan
ps - I should mention that I don't have to use java.net.URL, anything that's equivalent will work.
Your second option is the "right" option. The call to the external URL should be encapsulated in a service. The service, then, is injected into the servlet that uses it. This is one place where Inversion of Control comes in handy.
In your unit test you'd inject the test implementation, in real life you'd inject a real implementation. It can be as simple as providing a setter for the service and defaulting the implementation to the "real" one.
This kind of thing is a canonical example for IoC/DI.
Looks like you are reinventing the wheel - and you invented it yet again in Example 2. This is typically implemented using dependency injection and is actually the best solution software developers came up with so far.
Hide your web service call behind an interface. One implementation does the actual call while the other is a mock that you can configure. If you are not using any DI framework (Spring, Guice, EJB/CDI), replace production implementation with mock manually in the test.