Hacker News new | ask | show | jobs
by kaba0 1653 days ago
Spring does (and perhaps even prefers where possible) constructor-based inheritance though — which is as pluggable as it gets, making testing easy.
1 comments

> Spring does (and perhaps even prefers where possible) constructor-based inheritance though

OFC Spring does lots of things (too many things), but that varies project to project based on what series of Spring-related libraries are being used.

More likely I'll see non Spring-core annotations like @RestController + @RequestMapping-attributes and have to figure a standard way to mock up some of what Spring does just to assert the outputs. Perhaps there will be a series of full functional tests which requires a setup/teardown. Maybe the project just ignores endpoint tests and focus on the less Spring annotated business logic claiming "it's simple enough".

Spring has resulted in slow, complex, and incomplete (coverage) testing almost anywhere it's used because it's literally hiding functionality behind a runtime composition that you can't access casually by calling a routine.

It's problematic because it's complex and the versions

Testing REST-endpoints should be the job of integration tests, which are by definition more involved. Also, spring has really great test suits for these use cases.

Other classes/components should in the general case be written as POJOs. The dependent components can be mocked/injected simply by using the constructor.

> Testing REST-endpoints should be the job of integration tests, which are by definition more involved.

I would confidently say, this philosophy is dead wrong. Integration test are useful, but you still want the unit tests to ensure that the code paths and side effects are maintained. With runtime composition, this is much harder. Java sacrificed what we do know for a grand experiment of doing as much as possible in pre-processing, breaking (sacrificing) the known concept of code reliability in the hopes that someone else would figure out a way to handle the testing implications down the line. Java Testing went from a gold standard to an afterthought with annotations. This is how important getting additional composition turned out to be, but at what cost?

> spring has really great test suits for these use cases.

@SpringBootTest requires booting up Spring just to add in the runtime composition. It's both unnecessarily time consuming and problematic to have to predict composition rather than observing it directly. Now you have to memorize what Spring might do, given annotations that can be anywhere AND the code you are trying to test. Nightmare stuff.

How would you test a REST endpoint, if I may ask? Because in the end it will somehow reply to a request. But that response has quite a few things going on — if you give back the url of a templates string as a constant, is that meaningful to unit test that? For anything more complex you should be writing a service which can and should be unit tested. But I believe that the set of headers, security! and the like is not in the realm of the quite complex job of endpoints. By that you would be testing the Spring library, which presumably happens on spring’s side.
> How would you test a REST endpoint, if I may ask?

Functional test (or integration test if you like). That wasn't the point.

> For anything more complex you should be writing a service which can and should be unit tested.

You're special casing a function based on how it's placed in the flow of the project. Unit (fn being a unit) tests are necessarily agnostic as to the overall functionality. If you want to special case how you are handling functions in a project, good luck. You'll continue to have failures that you'll handwave away as "not following the patterns" or "simple mistakes" rather than recognizing that you should have had useful unit tests to prevent it.

People often conflate the reasons that unit testing doesn't prevent bugs. The primary weakness of unit testing is that you cannot assert "no additional functionality" in the function implementation (code). When languages adopt testing as a first class concern and provide function hashes as a validation, we will see it adopted en-mass and these runtime compositions strategies will be left out, and rightly so.