TDD: how to test data persistence abstraction - tdd

problem statement
Let's say I want to implement a simple key-value storage, which provides basic CRUD operations. The only requirement is that all the modifications should persist between application launches. I'm not concerned about particular persistence mechanism, as it may change during development, or even be different depending on the platform.
the question
How should I approach testing such library / class / module (whichever it becomes in the end) ?
All the answers I found were focused on testing particular database solution, but that's what I want to avoid. I'm only concerned about the fact that changes are being persisted, not about how they're persisted.
Solutions I considered:
extract the actual persistence implementation, and test each implementation separately, and only test if the abstraction layer calls correct methods
The problem I see with this approach is large amount of code for very simple task, and the fact I'm still concerned about particular persistence mechanism in the end. This may complicate development, especially for such a simple thing as a key-value storage.
make some test that actually launches the application multiple times, and checks if the data changes are persisted between launches
That would test exactly what I need, but such a test would probably be expensive, and not necessarily easy to write.
Test only if the methods work for single process, do not test persistence at all
Well, the whole point of the library would be to test persistence. Say, some user settings, or game save. Testing if it works in memory doesn't test the real problem.
Maybe some other solution, I didn't think of?
I've read through most of the topics related to persistence and TDD here, and on other sites, but all I could find focuses on specific persistence mechanism.
somewhat related, but doesn't touch on the testing subject:
How many levels of abstraction do I need in the data persistence layer?

A persistence layer is a port of your application. As such, your approach should be to write an adapter to that port, and test that adapter using an integration test.
The test itself doesn't need to spin the adapter more than once - testing that things actually persist would be testing the persistence mechanism itself, and that's not your concern. At some point, you'll have to assume things work, and they have their own tests to make sure that's correct. A typical write and then read back test would do for most cases.
Once the adapter exists, you can use several techniques for writing other tests - mock the adapter when it is a collaborator for other units, or use an in-memory implementation of the adapter (using a contract test to see that the in-memory implementation is the same as the other one).

Related

Not seeing people use interfaces and #Transactional in their Spring Applications

I have been seeing this trend recently with some Spring Framework developers. When they create their Service classes they are not creating interfaces for them to implement and they are not using #Transactional in their service classes when they are definitely in need of transactions.
Is there a good reason for this?
And one more question, Spring Boot has Session In View set to be true. Why? I always thought that to be a really bad design, allowing for developers to be lazy and allow for N+1 queries to happen all the time and slowing down performance. If you know you are going to need it for the UI, why not query for it in the Service-Repository classes in the least amount of queries instead?
It's true that building Services with interfaces and class implementations has been under questioning lately. There a classic post about this: https://octoperf.com/blog/2016/10/27/impl-classes-are-evil/ .
About Transactions, for read operations the readOnly=true parameter should be included in the #Transactional annotation to make sure it is done properly. As for the write operations, of course the transaction management should be done with care and the #Transactional annotation is there to make sure it is done so. Not using it is certainly a code smell, since a transaction will happen nonetheless, but you just won't have control over it.
Session In View set to true is a code smell too, and it should be used in learning environments or short-term experiments only. Batching, among other possibilities, can and should be used to avoid the N+1 problem.

Is it worth implementing service integration tests in Spring Boot application?

I have come accross multiple articles on integration testing on Spring Boot applications. Given that the application follows three layer pattern (Web Layer - Service Layer - Repository Layer) I have not seen a single article with integration testing the application up to just the service layer (ommiting the web layer) where all the business logic is contained. All of the integration tests seem like controller unit tests - mostly veryfing only request and response payloads, parameters etc.
What I would like however is to verify the business logic using service integration tests. Since the web layer is responsible only for taking the results from services and exchanging them with the client I think this makes much more sense. Such tests could also contain some database state verifications after running services to e.g. ensure that there are no detached leftovers.
Since I have never seen such a test, is it a good practice to implement one? If no, then why?
There is no one true proper way to test Spring applications. A general approach is as you described:
slices tests (#DataJpaTest, #WebMvcTest) etc for components that heavily rely on Spring
unit tests for domain classes and service layer
small amount of e2e tests (#SpringBootTest) to see if everything is working together properly
Spotify engineers on the other hand wrote how they don't do almost any unit testing and everything is covered with integration tests that covered with integration tests.
There is nothing stopping you from using #SpringBootTest and test your service layer with all underlying components. There are things you need to consider:
it is harder to prepare test data (or put system under certain state), as you need to put them into the database
you need to clean the database by yourself, as (#SpringBootTest) does not rollback transactions
it is harder to test edge cases
you need to mock external HTTP services with things like Wiremock - which is also harder than using regular Mockito
you need to take care of how many application contexts you create during tests - first that it's slow, second each application context will connect to the database, so you will create X connections per context and eventually you can reach limits of your database server.
This is borderline opinion-based, but still, I will share my take on this.
I usually follow Mike Cohn's original test pyramid such as depicted below.
The reason is that unit tests are not only easier to write but also faster and most likely cover much more than other more granular tests.
Then we come across the service or integration tests, the ones you mention in your question. They are usually harder to write simply because you are now testing the whole application and not only a single class and take longer to run. The benefit is that you are able to test a given scenario and most probably they do not require as much maintenance as the unit tests when you need to change something in your code.
However, and here comes the opinion part, I usually prefer to focus much more on writing good and extensive unit tests (but not too much on test coverage and more on what I expect from that class) than on fully-fledged integration tests. What I do like to do is take advantage of Spring Slice Tests which in the pyramid would be placed between the Unit Tests and the Service Tests. They allow you to focus on a specific class (a Controller for example) but they also allow you to test some integration with the underlying Spring Framework or infrastructure. This is for me the best of both worlds. You can still focus on a single class but also test some relevant components of your application. You can test your web layer with #WebMvcTest or #WebFluxTest (so that you can test JSON deserialization and serialization, bean validation, etc...), or you can focus on your persistence layer with #DataJpaTest, #JdbcTest or #DataMongoTest (so that you can test the actual persistence and retrieval of data).
Wrapping up, I usually write a bunch of Unit Tests and then web layer tests to check my Controllers and also some persistence layer tests against a real database.
You can read more in the following interesting online resources:
https://martinfowler.com/articles/practical-test-pyramid.html
https://www.baeldung.com/spring-tests

Usecase of Spring DAO

I'm wondering what is the typical usecase of Spring DAO where we can easily switch between different persistence frameworks.
Apart from abstracting the boiler-plate code (for JDBC, Hibernate like) Why does any application want to change its ORM frameworks so frequently?
By using a DAO pattern with a distinct DAO interface, this enables you to mock the DAO implementation. With this you improve testability of your code, as you are then able to write tests that do not need database access.
It is not only about frequently being able to switch between ORM frameworks, but is also about reducing effort if you are enforced to change the ORM.
Another reason is, that you might have different data sources like a database, a webservice or the file system for example. In this case you don't abstract the ORM but simply the persistence mechanism in general.
I think the real important idea behind DAOs are that you have just one spot where all data access related code for a particular entity ist located. That makes testing and refactoring of your persistence layer easier and your code is better readable.
Furthermore, it makes the code better readable. Think of a new developer in your team that should implement a feature. If she needs to access the databasase she would look into the dao for data access methods.
If you scatter the data access code in different services the risk is pretty high that someone produces code duplicates.

EJB3.1 Remote invocation - is it distributed automatically? is it expensive?

I'm building a JEE6 application with performance and scalability in the forefront of my mind.
Business logic and JPA2-facade is held in stateless session beans (EJB3.1). As of right now, the SLSBs implement only #Remote-interfaces. When a bean needs to access another bean, it does so via RMI.
My reasoning behind this is the assumption that, once the application runs on a bunch of clustered application servers, the RMI-part allows the execution to be distributed across the whole cluster automagically.
Is that a correct assumption?
I'm fine with dealing with the downsides of that (objects lose entityManager session, pass-by-value), at least I think so. But I am wondering if constant remote invocation isn't adding more load then necessary.
The EJB specification don't specify how clustering should be achieved, so this will depend on the particular implementation used. Actually, the EJB specifications are on purpose written to not make assumptions about the deployment: they don't mandate any support of clustering, but are written in a way that makes it possible (and a lot of restrictions in the EJB model stems from potential clustering issues, e.g. access to the file system). The implementer is then free to support clustering or not, and still comply with the spec.
In Glassfish, the reference to the remote EJB does the distribution itself. See my answer here for more information. Each request could potentially be dispatched to a different node. That's probably the way most implementations work. So I would say your assumption is correct.
I do hope however that they optimize the case when one EJB calls another EJB and try to dispatch the invacation on the same node whenever possible. That will depend whether the deployment is homogeneous or not (all nodes have the same beans, or not). Again, the spec are a bit vague regarding such points. But I guess that most deployment are homogeneous in practice: the same ear is deployed on all nodes.
Regarding the performance overhead of remote vs. local calls, I did some measures once (on Glassfish). See my answer here. Inter EJB calls in the same .ear through remote interface was 3x slower than local calls. That sounds big, but we are speaking of milliseconds, so the relative overhead depends on what the methods really does. I don't know the performance of other app. server.
Hope it helps.

What are the advantages and disadvantages of the Session Façade Core J2EE Pattern?

What are the advantages and disadvantages of the Session Façade Core J2EE Pattern?
What are the assumptions behind it?
Are these assumptions valid in a particular environment?
Session Facade is a fantastic pattern - it is really a specific version of the Business Facade pattern. The idea is to tie up business functionality into discrete bundles - such as TransferMoney(), Withdraw(), Deposit()... So that your UI code is accessing things in terms of business operations instead of low level data access or other details that it shouldn't have to be concerned with.
Specifically with the Session Facade - you use a Session EJB to act as the business facade - which is nice cause then you can take advantage of all the J2EE services (authentication/authorization, transactions, etc)...
Hope that helps...
The main advantage of the Session Facade pattern is that you can divide up a J2EE application into logical groups by business functionality. A Session Facade will be called by a POJO from the UI (i.e. a Business Delegate), and have references to appropriate Data Access Objects. E.g. a PersonSessionFacade would be called by the PersonBusinessDelegate and then it could call the PersonDAO. The methods on the PersonSessionFacade will, at the very least, follow the CRUD pattern (Create, Retrieve, Update and Delete).
Typically, most Session Facades are implemented as stateless session EJBs. Or if you're in Spring land using AOP for transactions, you can create a service POJO that which can be all the join points for your transaction manager.
Another advantage of the SessionFacade pattern is that any J2EE developer with a modicum of experience will immediately understand you.
Disadvantages of the SessionFacade pattern: it assumes a specific enterprise architecture that is constrained by the limits of the J2EE 1.4 specification (see Rod Johnson's books for these criticisms). The most damaging disadvantage is that it is more complicated than necessary. In most enterprise web applications, you'll need a servlet container, and most of the stress in a web application will be at the tier that handles HttpRequests or database access. Consequently, it doesn't seem worthwhile to deploy the servlet container in a separate process space from the EJB container. I.e. remote calls to EJBs create more pain than gain.
Rod Johnson claims that the main reason you'd want to use a Session Facade is if you're doing container managed transactions - which aren't necessary with more modern frameworks (like Spring.)
He says that if you have business logic - put it in the POJO. (Which I agree with - I think its a more object-oriented approach - rather than implementing a session EJB.)
http://forum.springframework.org/showthread.php?t=18155
Happy to hear contrasting arguments.
It seems that whenever you talk about anything J2EE related - there are always a whole bunch of assumptions behind the scenes - which people assume one way or the other - which then leads to confusion. (I probably could have made the question clearer too.)
Assuming (a) we want to use container managed transactions in a strict sense through the EJB specification then
Session facades are a good idea - because they abstract away the low-level database transactions to be able to provide higher level application transaction management.
Assuming (b) that you mean the general architectural concept of the session façade - then
Decoupling services and consumers and providing a friendly interface over the top of this is a good idea. Computer science has solved lots of problems by 'adding an additional layer of indirection'.
Rod Johnson writes "SLSBs with remote interfaces provide a very good solution for distributed applications built over RMI. However, this is a minority requirement. Experience has shown that we don't want to use distributed architecture unless forced to by requirements. We can still service remote clients if necessary by implementing a remoting façade on top of a good co-located object model." (Johnson, R "J2EE Development without EJB" p119.)
Assuming (c) that you consider the EJB specification (and in particular the session façade component) to be a blight on the landscape of good design then:
Rod Johnson writes
"In general, there are not many reasons you would use a local SLSB at all in a Spring application, as Spring provides more capable declarative transaction management than EJB, and CMT is normally the main motivation for using local SLSBs. So you might not need th EJB layer at all. " http://forum.springframework.org/showthread.php?t=18155
In an environment where performance and scalability of the web server are the primary concerns - and cost is an issue - then the session facade architecture looks less attractive - it can be simpler to talk directly to the datbase (although this is more about tiering.)

Resources