I am writing test case for my webflow using org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests
public class MyFlowExecutionTests extends AbstractXmlFlowExecutionTests {
}
In some cases my logic is simple, So I invoke my service layer directly from the Spring webflow.
In some cases I use an extenstion of org.springframework.webflow.action.MultiAction classes and I invoke my service layer from the action classes.
In the first scenario, wrting test case is straight forward. In the second scenario, I found it really complex to write the test cases using org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests for the Action class.
In the first scenario, I can mock all the service classes used from my flow. In the second scenario, using easy mock class extension, I can mock the action class. But then I need to mock the service layers used inside, which I think mock can't handle that well.
I am now thinking of somehow moving the Action class code to Spring EL. Or Anybody have a better idea for testing the action class code along with webflow code?
Related
I use Spring Boot with Kotlin and my project is splitted on modules where I have application layer with REST controllers and facades, domain layer with services and business logic and infrastructures layer for communication with external services or DBs. I think (but I can be wrong) that the best place for basic validation like notNull, notEmpty, max and min, size etc. is facade because both REST controllers and another modules communicate with it, but the problem is that javax validation annotation like #Valid are working only on REST Controller layer (in classes with annotation #RestController) and when I try to create some tests for this facade then fields with wrong values return NullPointerException instead of MethodArgumentNotValidException. I tried to create WebMvcTest but also returns wrong exception. Is it some solution for it? I saw that I could call some validator inside the method but it looks like much more complex approach than annotation on method's argument.
You can inject the javax.validation.Validator into any Spring component. For example, into a facade component, and perform validation in the facade layer:
#Autowired
Validator validator;
Set<ConstraintViolation<UserRequestDTO>> violations = validator.validate(userRequest);
This way you can remove the #Valid annotation from controllers at all. And this approach puts validation results under the your control.
I am mocking a repository with the annotation #mock and then saving some data to the repository in the test class. Is the data really getting stored in the repository?
In another class when the same data is fetched it is showing not found. How will I test my class if the data is not stored in the repository?
Most likely, when you use the #Mock annotation correctly in your test code, your mocking framework will come and instantiate something for you under that name:
#Mock
WhatEver someWhatEver;
In other words: when the above "executes", someWhatEver will reference some object that conforms to the "API" that the WhatEver class provides.
Meaning: you can call all methods that exist on that class. And nothing will happen. Because someWhatEver isn't a instance of your real production class. It is something that looks like it.
Thus, the real answer is: you step back, and you research the whole topic. There is no point in doing "unit testing" using some mocking framework without "understanding" what you are doing. The tutorial by vogella is a good starting point.
Mocking is a way to encapsulate your unit tests. If you want to test a service method you are not interested if the repository is working. For this you will write repository tests. Therefore you mock the repository call and tell which result should be returned to test your method in all possible situation. The mock itself is a proxy, therefore there the data which are you saved are not really safed in your database. This has the advantage that you havenĀ“t to start your whole context and the tests are much faster.
When we want to do a Service Unit Test in SpringBoot Application We have not gone use Real DataBase just we need to Mock DataBases.
Similarly When u want to do Unit Test any External Serivce in Your class Just U can Mock that External Service call.
A Mockito mock allows us to stub a method call. That means we can stub a method to return a specific object. For example, we can mock a Spring Data JPA repository in a service class to stub a getBooks() method of the repository to return a Book object.
I am working on the project where I want to have decent test-infrastructure.
I am using spring boot, which makes easier for testing separate layers of the project: for example
If I want to test controller layer I will mock (with mockito) service dependencies of the controller, and check whether right service method will be called on given http request, and expected http status will be returned. If I want to test service layer I will mock repository and business logic dependencies. And so on.
In my project, I am using spring validators to check whether request body is passed correctly (with the use of #InitBinder method I am adding my custom validators to the WebDataBinder, and with use of #Valid annotation, those validators are called on the parsed request body).
So my question is: is it good practice to mock validators and test only controller logic (validators will be tested in context of validator layer)?
I am just not sure which is the best practice, and is it normal to test validators along with controllers?
Mocking is not always best option, when you are testing your controller logic, validation logic and especially business logic. I would not recommend to mock any of these.
You can use various framework to test:
Controller logic - RestAssured or MockMvc
Business logic - Plain JUnit tests under SpringBootTest and SpringRunner
Validation logic - Plain JUnit tests under SpringBootTest and
SpringRunner
For further reading:
RestAssured: http://rest-assured.io/
Spring validator test: Writing JUnit tests for Spring Validator implementation
I am developing a web application using Spring + Hibernate, plus CXF to convert my Service layer into a WebServices endpoint. I want to unit test my code, and when it comes to the DAOs I have no trouble: I create an in-memory database filled with my test data, then test DAOs against that.
But when testing the Service layer, most of my methods are like these:
#Override
#Transactional
public void saveProgramacion(ProgramacionDTO programacion) {
programacionDAO.persist(this.map(programacion, Programacion.class));
}
That is, my method just maps the VO to a DTO (using an external mapper) then calls a method of my DAO. Just that.
I used mockito to mock my DAO but honestly there are no instructions to provide mockito with since the service method itself does very little and does not check the DAO result. Given the fact that the mapper is an external dependency and thus would require its own unit test, what should I be testing here? What would be a proper unit test in this case?
Researching the use of inheritance in Spring MVC.
Is it a good idea to have a base controller that other controllers can extend ?
The base controller would be to hold functionality common to all controllers.For E-g getting a handle to the logged-in user etc.
If using the base controller is not a good idea are there any other suggestions to implement something like what I have mentioned above.
It is perfectly acceptable to have a base controller that other controllers can extend. When Spring introduced #Controller annotations, they paved the way for you to use whatever class hierarchy you want.
Just be aware that as an object oriented design principle, it's good to favor composition over inheritance. As a rule of thumb (not a hard and fast rule) I would recommend moving your common controller code into a class whose interface can be injected into your controllers via #Inject or #Autowired.
Another suggestion for getting a handle to the logged-in user is a little more work but very nice once you have it. See the discussion here about using a current user annotation on your controller method arguments. This is what I do on my project and it works great!