No Mocking on MongoRepository - spring

I have the following configuration
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootApplication(scanBasePackageClasses= {})
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes= {})
#ActiveProfiles("local")
I want to run a JUnit test without mocking the MongoRepository calls but it automatically mocks the MongoRepo calls and gives back null. Is their a way around it?

Firstly, you should decide what kind of test you want to perform,
Unit test
or
Integration test
If you are doing unit test , you should write separate test cases for each layer
Controller layer - use mockmvc and mock service layer calls
Service layer - Here you have two options, YOu can mock repository calls or you can use some in memory database(like Fongo) and put some data before testing and test it.
If you want to test all layers together and with real database then you should write Integration tests.

Related

What does Mocking a repository mean in mockito?

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.

Kotlintest with Spring Test, #Transactional not working/applied

I have a problem getting Spring Boot 2.0.5 to work nicely with Kotlintest 3.1.10.
I made a test project illustrating the problem I have.
The project is a Spring Boot 2 application
with two entities, ShoppingOrder and OrderLine (to be totally unimaginative).
There is also a test case ShoppingOrderSpec which just tests the mapping by storing and retrieving the Order.
The testcase is configured like this:
#ExtendWith(SpringExtension::class)
#Transactional
#SpringBootTest
class ShoppingOrderSpec : WordSpec() {
override fun listeners() = listOf(SpringListener)
The test case is using the SpringExtension
by Spring to hook into the JUnit 5 engine. It also uses the SpringListener and Wordspec from Kotlintest to structure the tests
and do the assertions.
The SpringListener correctly autowires the dependencies, but somehow the transaction is not being created.
Running the testcase gives the following stack-trace:
2018-10-12 10:54:14.329 INFO 59374 --- [intest-engine-0] com.example.demo.ShoppingOrderSpec : Started ShoppingOrderSpec in 4.478 seconds (JVM running for 7.421)
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.demo.ShoppingOrder.lines, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
...
at com.example.demo.ShoppingOrderSpec$1$1.invoke(ShoppingOrderSpec.kt:35)
at com.example.demo.ShoppingOrderSpec$1$1.invoke(ShoppingOrderSpec.kt:19)
So, somehow the org.springframework.transaction.annotation.Transactional annotation does not seem to work,
as removing the annotation, just gives the same response.
Anyone any ideas how to get the #Transactional being applied and respected?
You can't use JUnit Jupiter extensions with KotlinTest as they are different engines. Junit Jupiter is an implementation on top of Junit Platform, like KotlinTest is, but anything written specifically for Jupiter won't work with KotlinTest. Anything written for Junit Platform should work however.
Unfortunately, the naming choices by the JUnit team are poor imo, and so people think JUnit Jupiter is the same thing as JUnit Platform.
Anyway, those
#ExtendWith(SpringExtension::class)
#Transactional
#SpringBootTest
extensions are not going to mean anything to KotlinTest, anymore than they would for Spek or whatever. ExtendWith is a Jupiter specific annotation that tells it to use the SpringExtension class. The KotlinTest equivilent is SpringListener which you've already wired in.
I'm not sure if #SpringBootTest will be picked up or not by Spring. Support may need to be added for that depending on what it does.
Finally #Transactional works by creating proxies on the methods, but since in more advanced testing frameworks like KotlinTest, the test containers are not methods, but just arbitrary functions, it won't be able to intercept.
I think in this case, you might need to create a proper method and annotate that, or try using the AnnotationSpec rather than StringSpec or whatever other spec base class you are using, which uses actual methods that you could annotate.

Spring boot: should validation been tested when testing controller layer

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

WebServices, what to unit test?

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?

Testing Spring Webflow Action Classes

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?

Resources