Im trying to understand how all things are related with Spring. However I do not understand why mockito is used when unit testing spring code? Can not spring handle to same DI that mockito does? What is it that mockito contributes that is not possible to do with pure spring?
Clarification:
My thinking goes that I can just use a different application context for testing where I create the stub beans I need as dummy objects.
Spring is not a mocking framework. It's a dependency injection framework.
You use Mockito because it allows mocking collaborators of the class under test. So, if you're testing a service, and this service uses a repository that gets and stores data in a database, you mock the repository so that your test is a real, isolated unit test that doesn't need an Oracle database to run.
Read https://stackoverflow.com/a/28783849/571407 for a more detailed introduction to mocking.
You don't need Mockito to test Spring applications. You can start your server and use the injected dependency directly. But sometimes it is easier to mock one (or more) dependency(ies), for example a select of your database, because you want to test the code that you have written and not the select of the database, which also includes that you need a database with some testdata (or at least mocked testdata). In fact you use Mockito to keep dependencies of your tests out, so you can test the code that your application uses and to "ignore" dependencies of third party test environments.
Related
Need General Idea
What can qualify to be good unit test in spring boot?
Areas of discussion
Should we use #Autowired to call another class in unit test or everything use Mock.
#Mock Vs #MockBean
If we use #Mock and #Autowired together in Unit test class, can it be still a qualified to be unit test or becomes Integration test.
NOTE: Aware of #RunWith to make Integration and Remove Integration. My Question stress more about writing a good unit test in spring boot applications.
Thanks
It is generally a good practise to use #Mock for the dependencies while unit testing. you would not certainly need to load spring context to run your unit cases. When using Mocks, the test can be run independent of the spring context. #Autowired in unit testing slightly behaves more of an app integration testing where you are loading the spring context ,at least slice of it for the testing.
Consider a method like this PerformPayment(double amount, PaymentService service);
A unit test would be a test where you create a mock for the service argument.
An integration test would be a test where you use an actual external service so that you test if that service responds correctly to your input data.
If I go deeper in details
Unit tests are tests that the tested code is inside of the actual class. Other dependencies of this class are mocked or ignored, because the focus is to test the code inside the class.
Integration tests are tests that involve disk access, application service and/or frameworks from the target application. The integration tests run isolated from another external service.
I will give an example. You have a Spring application and you made a lot of unit tests to guarantee that the business logic is working properly. Perfect. But what kind of tests you have to guarantee:
Your application service can start
Your database entity is mapped correctly
You have all the necessary annotations working as expected
Your Filter is working properly
Your API is accepting some kind of data
Your main feature is really working in the basic scenario
Your database query is working as expected
Etc...
This can't be done with unit tests but you, as a developer, need to guarantee that all things are working too. This is the objective of integration tests.
The ideal scenario is the integration tests running independently from another external system that the application use in a production environment. You can accomplish that using Wiremock for Rest calls, a memory database like H2, mocking beans from some specific classes that call external systems, etc.
A little curiosity, Maven has a specific plugin for Integration Tests: the maven failsafe plugin, that executes test classes that the name ends with IT. Example: UserIT.java.
Read more by guru
https://martinfowler.com/bliki/IntegrationTest.html
What's the difference between #RunWith(MockitoJUnitRunner.class) and #RunWith(SpringJUnit4ClassRunner.class)? When to use it appropriately?
MockitoJUnitRunner
specific for use with the Mockito test framework
the Mockito framework helps with mocking dependencies when you want to focus your tests on a single class and avoid invoking methods on dependencies (instead invokes a mock/dummy that is easily configured).
Above is what mockito is used for, but for more on this runner specifically - from the docs: "keeps tests clean and improves debugging experience". "Runner is completely optional - there are other ways you can get #Mock working". Source - https://static.javadoc.io/org.mockito/mockito-core/2.6.8/org/mockito/junit/MockitoJUnitRunner.html
SpringJunit4ClassRunner
specific for use with the spring framework
used for integration tests when it is required to load the spring context (create spring beans, perform dependency injection, etc).
In integration tests you may not do as much mocking of dependencies but you can do both in the same test.
Integration tests are useful when you would like to test loading the spring context or perhaps test from the service/high level all the way down to lower levels like data access with a single test.
In some cases you may want to use both - like an integration test where you would also like to mock some dependencies (perhaps they make remote calls). Unfortunately you can't use two #RunWiths but this is a good post about that - Multiple RunWith Statements in jUnit
I am working on a Java web app with unit/integration tests. App gets deployed to Jetty and uses H2 db while running the integration test phase of maven. I've one oracle function which is called from dao layer which can not be migrated to H2 db, hence i want to mock/skip this part in code while running the test cases.
I thought of having a flag which can tell if i'm running application in test mode and put the condition in code for it, but doesn't look like cleaner approach to me. Please suggest best approach to achieve this.
Extract the Oracle native call into a separate class (probably some DAO). Inject that DAO to class that uses it. Create a second implementation of that DAO, doing nothing in place of calling Oracle. During integration testing inject the latter implementation.
Avoid flags in your code. If you are using Spring, use build profiles that will selectively create one implementation or the other.
That's how dependency injection helps you test your code: if you want to mock some part of the system, just inject mocked version.
Please use some good Mocking frameworks such as mockito or jMock or some other similar mock frameworks.
Please Note: You might be required to re-factor your code to make it more testable.
If the question truly is:
How do I skip a section of code when unittesting in java
then I agree with the answers given. Dependency injection, mocking frameworks are absolutely the right way to go to do true unit testing.
However if the question is:
How do I skip a section of code when using JUnit (or other unit testing framework)
Then I think the answer is "it depends". Sometimes I use JUnit for integration testing - snippets of client code that I run against a test server to save me the trouble of doing these client side tests manually via a GUI. In this case I use system properties for example in my base class I have:
protected boolean skipTest()
{
String port = System.getProperty("jersey.test.port");
// don't run this test unless developer has explicitly set the testing properties
// this is an integration test, not a unit test
return port == null;
}
Then in the actual test class it looks like this:
// verify a successful login
#Test
public void testLogin()
{
if (skipTest())
return;
// do real test
So, my thought is if you really cannot refactor the Oracle stuff out of your DAO, then you really are doing an integration test and it's OK to have a skipTest in your unit test.
I recently managed to convince my mates in the project that we need testing (!). Due to the highly dynamic and flexible structure of our web application, with behavior depending of lots of parameters and permission relationships, they had rejected testing altogether, for the usual reasons (time consuming, test maintenance, etc.).
We will introduce testing at the service layer:
Web Browser -> GWT/RPC -> GWT Servlet -> RMI -> SessionEJB -> RMI -> Spring beans
Thus after the GWT Servlet.
Do people recommend to use junit? Or are there other test frameworks better suited? Any other general suggestions? Thanks
You can indeed use plain JUnit or TestNG with a mock framework to test your SessionEJB and individual Spring beans in isolation, i.e. proper Unit testing.
But since there is already a lot of code written, you'll probably find more bugs with less code using system testing or integration testing, i.e. test your complete SessionEJB and spring beans roundtrip in a test application context, with even a real database behind.
For integration and system testing, you can use DBUnit to have a fixture of test data in a database. And Spring also has a lot of test support utils. All of this things work with both JUnit and TestNG.
You should be able to JUnit your Servlets & EJBs. I suggest using some kind of mock framework (e.g. EasyMock) for your servlet context and if you are using any kind of JNDI resource or dependency injection.
As for a testing framework, I highly recommend TestNG (http://testng.org), with Mockito (code.google.com/p/mockito/). I love using both due to their ease of use. #DataProvider in TestNG helps me a lot, as well as other annotations for setting up a test before/after running. I was using JUnit before until I met TestNG at work and don't think I'll be going back anytime soon :)
Check them out, TestNG is definitely picking up some steam and gaining reputation.
I'm starting on testing applications in general and I want to create several tests to learn Mockito in Spring. I've been reading several information but I have some general doubts I'd like to ask.
I have seen come Mockito tests and they annotate the test of the class with: #RunWith(MockitoJUnitRunner.class) while in the Spring documentation it is used #RunWith(SpringJUnit4ClassRunner.class). I don't know what's the difference between them and which one should I use for a Spring application where tests use Mockito.
As I haven't seen any real application that has test I'd like to know typical test that a developer would do. For example in a typical CRUD application for users (users can be created, updated...) can anyone a usual test that it would be done.
Thanks.
#RunWith(MockitoJUnitRunner.class)
With this declaration you are suppose to write a unit test. Unit tests are exercising a single class mocking all dependencies. Typically you will inject mocked dependencies declared like this in your test case:
#Mock
private YourDependency yourDependencyMock;
#RunWith(SpringJUnit4ClassRunner.class)
Spring runner is meant for integration test (component test?) In this type of tests you are exercising a whole bunch of classes, in other words you are testing a single class with real dependencies (testing a controller with real services, DAOs, in-memory database, etc.)
You should probably have both categories in your application. Althought it is advices to have more unit tests and only few smoke integration tests, but I often found myself more confident writing almost only integration tests.
As for your second question, you should have:
unit tests for each class (controller, services, DAOs) separately with mocked all other classes
integration tests for a whole single CRUD operation. For instance creating a user that exercises controller, service, DAO and in-memory database.