4 ms·
Is it hard to write ONE test case for ALL getters and setters using reflection?
by oneshtein 3y ago
Is it hard to write ONE test case for ALL getters and setters using reflection?
- reactordev 3y agoat that point what are you testing? allocation/deallocation? Nothing is actually happening unless you depend on constructors/destructors when you use reflection to gen a mock type or real value type to inject. Or do you mean just assert true that all getters are not null? I agree that unit testing for the sake of KPI's is the wrong approach and unit testing functionality (as a means of documenting it, proving it still works as intended) is far better.
- oneshtein 3y ago> at that point what are you testing? Memory. > Nothing is actually happening unless you depend on constructors/destructors when you use reflection to gen a mock type or real value type to inject. Just get an object from IoC container, then test that getFoo() == getFoo(setFoo(getFoo())) for every Foo with get and set methods, so you will have 80% of coverage for those getters and setters. For read-only properties, just get value and throw it away. > I agree that unit testing for the sake of KPI's is the wrong approach and unit testing functionality (as a means of documenting it, proving it still works as intended) is far better. Unit tests are for proving correctness of logic in a unit of code. Data structures are not logic. IMHO, such trivial parts of program should be ignored by coverage tool, but topic starter said that they cannot change rules. :-/
- growse 3y ago> > at that point what are you testing? > Memory. In unit testing, the "memory" is not the system under test though.
- zarathustreal 3y ago>> at that point what are you testing? > Memory. It doesn't make sense to test something you have no control over, if the OS fails to allocate memory there's nothing you can change in your code to fix that. Likewise, if you're improperly instructing the OS to allocate memory (via some constructor or factory or whatever) there is no test you can write to test your own intentions that won't be subject to exactly the same level of incorrectness as the implementation code itself. If you've written "do the thing" writing a "test" that says "hey make sure I wrote 'do the thing'" is ridiculous. I've often found this to be a matter of semantics. Someone will say they're writing a "unit test" and load all the assertions and logic associated with the meaning of "unit test" into their brain and then try to apply it in a way that subtly invalidates those assertions when they start writing. To make things worse, there's a cultural disinclination toward "semantic arguments" so you end up arguing with people that have basically no chance of understanding why what they're doing doesn't provide the value it should
- Mawr 3y agoYou shouldn't have setters in the first place. What's the point of encapsulation if anyone can just set properties at will?
- noisy_boy 3y agoSometimes the value you pass to a setter can go through additional logic to determine the final value to be set e.g.: private int value1; private int value2; public void setValue2(int value2) { this.value2 = value2; } public void setValue1(int value1) { if (this.value2 > 0) { this.value1 = value1 + this.value2; } else { this.value1 = value1; } } Obviously this is a contrived example but if you have logic other than a simple "this.value = value", then you might want to unit test that bit.
- tom_ 3y agoAlso useful if you want to add logging, or capture some metrics, or set a breakpoint.
- growse 3y agoAh, the sound of people not using their type system properly. Parse, don't validate.
- reactordev 3y agoBut also don’t create AggregateNonNegativeInteger type when generics will do.
- ildjarn 3y agoSimplest solution? Don’t have any setters.
- thomasahle 3y agoRemoving them would reduce your coverage percentage.
- srvaroa 3y agoGood thing. It shows that a % of your tests were actually not targeted at the most important areas of the code base
- tauwauwau 3y agoI had to do it in one project. It's not trivial, but also not too difficult. Getters were easy, setters required different types of values. After handling various date type values for setters it worked fine. Occasionally I would see an exception for fields generated by APIs like Lombok, which needed to be excluded from my setter list. I didn't like that I had tobdo it, but it was easier than getting several approvals to get Sonar rules changed.
- jghn 3y agoOr stop using the broken pattern of getters and setters
- geraldwhen 3y agoI ask interview candidates to explain why they’re using getters or setters. They never have a reason.
- drowsspa 3y agoWould "because it's conventional and most tools and developers assume them" be an acceptable answer? The reason I read is "because you might wanna change the implementation" but honestly it's seems very rare to need to do that
- BlackFly 3y agoBecause your data structure and your API are separate things and generally speaking, the data structure should be opaque to users of that structure unless it's sole purpose is as a record for a bunch of request arguments. For those fat request structures, it ends up being a lot of noise indeed, but in any case most of those structures for most people are dealt with by deserialization and you can often skip generation of setters and getters or autogenerate them. Do you want to return a copy/clone of the inner object or just let people mutate it, destroying all of your data structure's invariants? Yes, if you change the implementation of the structure, user code will also break and it is certainly easier to do that behind a method, this is indeed rare in practice but the nuisance of migrating direct access to indirect access is bigger than the nuisance of (today's) unnecessary indirection. Since in some cases safety around invariants and future proofing will require the level of indirection, it is easier to just expect the convention. Moreover, codegen can just produce them for you, they can be excluded from test coverage. Then there are languages like python that allow you in the future to pretend that indirect access is direct access and cannot protect invariants in any case, so just go direct from day one.
- drowsspa 3y ago
- xxs 3y agoThe correct solution is not having either. Getter/setters are effectively an anti pattern as they support needless mutability but worse they add nothing of value. As a general rule most fields should be initialized in the c-tor, and they should be final.