• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

TDD becomes difficult when we are new to the spring boot framework

 
Greenhorn
Posts: 4
1
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
TDD becomes difficult when we are new to the framework
How do we ensure that we follow TDD even when we are new to the framework and have just started exploring the framework?
I have just started exploring Spring boot and find writing tests for services very challenging and following TDD approach feels something I cannot achieve right now. Do you have any suggestions on how I can improve in writing TDD tests especially for service layer.
Also should we follow TDD for pages rendered using thymeleaf?
 
Saloon Keeper
Posts: 27763
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch, Rupa!

Spring Boot's project generator generates unit-testing directories and support automatically.

Thymeleaf is, so I understand, a web-page templating language and the only real way to test web pages is via a web client system such as Selenium.
 
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Not everything needs to be done with TDD, in my opinion, and when something like Spring Boot becomes a limiting factor to doing TDD, then you're probably doing something wrong.

Another indication that you're not approaching TDD properly is asking "how can I improve in writing TDD tests...?" This makes me think your focus when doing TDD is testing or checking correctness. When I use TDD, it's primarily as a way to explore and clarify my understanding of the design of the system that's most appropriate for the problem at hand. I focus on domain and service layer behaviors. This is usually easily decoupled from things like Spring.
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It would help move the discussion along and help us give you more concrete advice if you gave an example of some kind of functionality you're trying to develop. Then tell, or better yet, show us how you intend to use TDD to develop that functionality. The more specifics we know about your context, the better advice we can give.
 
Tim Holloway
Saloon Keeper
Posts: 27763
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:This is usually easily decoupled from things like Spring.



Um. Spring itself is a decoupling mechanism. The idea being that Spring is at its base a mechanism for wiring together POJOs, and Unit Tests are normally testing POJOs, so it's all of a piece.

That's distinguished from the various Spring Modules such as Spring Web, Spring Security, Spring Data, and so forth - each of which was unit-tested by the Spring Foundation itself, designed to be injected into application POJOs. To unit-test POJOs that are injected with Spring Modules, you'd either inject a dummy module or a Mocked version of the Module in question.
 
Junilu Lacar
Sheriff
Posts: 17644
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:Um. Spring itself is a decoupling mechanism.


I'd argue that dependency injection is the decoupling mechanism. Spring is a framework that facilitates DI. You can do TDD on POJO that are totally unaware of the existence of Spring. If your tests are written in a way that makes them dependent on Spring, then you have actually coupled your design to Spring.
 
Author
Posts: 25
7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey Rupa,

Thanks for the question. You are correct that TDD is hard when you don't know the framework you are working with. More importantly know the techniques to verify the results of the framework you are using takes some practice. I have worked on several projects using Spring Boot during my time at Pivotal (the company that maintains Spring and is now owned by VMWare), we used TDD for all of the features we built.

Test-Driven Development with Spring Boot can be made easier by utilizing some of the features that the Spring team built—they use TDD too—to simplify testing. For instance, `@SpringBootTest` annotation allows you to get dependency injection inside of your test class. And `MockMvc` can make it easier to verify your controller is working correctly. And lastly `@MockBean` can allow you to easily create a test-double for a service or repository.

In order to help build understanding of the framework before you try to TDD a feature, I would recommend that you create a Spike. A Spike is a quick feature that you implement using non-production quality code to verify your understanding. Once you know how the pieces work, then you throw the code away and implement the feature using Test-Driven Development.

Testing thymeleaf is a bit hard, but I would recommend using MockMVC to make it easier. Here is the Spring resource on how you could test thymeleaf (https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#spring-mvc-test-server-htmlunit).

So that I can better answer your question about service layer testing, can you tell me more about the problem you are facing?

Thanks
Steve
 
Rupa B Lahiri
Greenhorn
Posts: 4
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you,

If I do the following in a service test, is it correct?



When I have already specified the same object to be returned through mocking, does it make any sense to check the same object and the returned object in an assert?

Next, it is best practice to specify a specific object to be passed as a parameter and a specific object after overriding the equals and hashCode methods, right?

When I have :



I get (I can put only parts of the message here):

Strict stubbing argument mismatch. Please check:
- this invocation of 'save' method:

  has following stubbing(s) with different arguments:
aTransactionRepository.save

Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
 - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
   Please use 'will().given()' or 'doReturn().when()' API for stubbing.
 - stubbed method is intentionally invoked with different arguments by code under test
   Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'save' method:
 
     -> at SomeServiceTest.java:190
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
 - stubbing the same method multiple times using 'given().will()' or 'when().then()' API
   Please use 'will().given()' or 'doReturn().when()' API for stubbing.
 - stubbed method is intentionally invoked with different arguments by code under test
   Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).

 
Steven Solomon
Author
Posts: 25
7
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Rupa,

Checking that the someObject is returned by the someService is a valid pattern. However, it should be the case that a service is doing a series of related steps and additional processing. Without seeing the full context of the code I wonder if the service instance is needed in this scenario. It may be an instance of the middleman code smell (https://refactoring.guru/smells/middle-man). I believe your service could be a middleman because it is simply returning the repository's value unprocessed.

The second part of your question gives me a similar design signal. The fact that the aTransactionRepository is being called multiple times with different objects may be an example of a mock objects anti-pattern know as "adding-behavior to the mock". This anti-pattern occurs when test code tries to emulate state changing by stubbing different response values based on calling parameters. This is something that I cover in more detail in the liveProject, but essentially the testing framework is giving you feedback that the contract of the aTransactionRepository is not quite right. It looks like you are trying to save a list of objects in one transaction. In order to resolve this, I would recommend changing the interface of your JPA Repo to have a saveAll method. That will eliminate the need to set Mockito to LENIENT mode.

If you have time, I'd be interested in seeing a more complete example, which includes a complete test and its production code. This would enable me to give you better feedback.

Thanks
Steve
 
Rupa B Lahiri
Greenhorn
Posts: 4
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you yes  
When one entity is been modified and saved, an entry is been made into the database through another entity which we created only for this purpose.
We are manually inserting data into a table which holds information on the two entities.
We had existing code to modify the first entity and we should have had a many to many relationship between two existing entities. Then we would have had a join table to have the information we are manually inserting.
I wonder how the tests would be rewritten if we were to use many to many.
I have used one to many and many to one and written tests for both.
I have not yet practiced creating many to many relationship and writing the tests for the same.
I looked for examples online and found one with integration tests and not individual tests for each layer, that is controller tests and service tests.

I apologize that I am unable to post code snippets as I have a few personal things I need to urgently look at and may have to step out, so I am unable to access my laptop which has the code today.

It is good you have created a live project for TDD for spring boot. I am sure it will guide many.
Thank you once again.
 
Marshal
Posts: 79179
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This thread has been quoted in the JavaRanch Journal (May 2022 edition), which earns the OP a cow.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic