Ivan Lorca wants to merge 0 commits from /u/speevy/opencsv/ to master, 2022-01-12
WHY: I have the need of formatting the numbers on the CSV output, mostly because of the distinct locale decimal point and miles separator symbols for several locales.
WHAT: I modified the ResultSetHelperService so you can define two number formatters: one for integer numbers and one for non integer (as floating point) numbers. If none of these is defined, the behaviour of the service remains the same it is now.
COMMENTS: In the way of applying this enhancement, I found what I believe is a bug causing that null numbers are rendered as 0, I also fixed it. Also I have had to change the way the resultset is mocked at test as the behaviour of the wasNull function was not consistent and made some tests to fail. I didn't find a way of doing it using mockito, so I used a simple wrapper with method call delegation.
| Commit | Date |
|---|
Sorry, I was wrong about the bug, my bad. The rest still applies.
I like this change, but I have a few questions:
1. If you say you fixed a bug, but then you say you were wrong about the bug, do you need to update this pull request?
2. Why use Generics in the two versions of applyFormatter()? It seems to me Number ought to work fine, unless I'm missing something.
3. I'm a little dubious about your claim that wasNull() behaves inconsistently. Could you walk me through why that change to the test code was necessary?
Hello Andew, thanks for your feedback.
I took a long, hard look at this today and made some changes before I committed:
1. You changed am expected test output for your proposed handleBoolean() method. Our project is quite strict that changing tests is not okay. Our extensive test suite is a contract with our users for how opencsv works. Changing a test means we broke backward compatability, and we only do that on major releases and for a good reason. So, I removed the handleBoolean() method and reverted the test change.
2. I am equally concerned about the changes to ResultSetHelperServiceTest for the same reason, but I don't understand Mockito at all, so I can't evaluate how your changes effect the overall test suite. As far as I can tell, all inputs and outputs are unchanged, and that's the key part.
3. But, your addition of
wnrl.add(value == null);to the end of MockResultSetBuilder.setExpectToGetColumnValue() is not showing up in the code I fetched. I'm probably doing something wrong, but everything else seems to be there, and I don't know why git would fetch everything except one line.4. I'm also terribly worried about the BigInteger case, which, from the former code in ResultSetHelperService should have returned the string "null" on null input, yet the unaltered tests indicate it returned an empty string. I can't explain that. I'm guessing it's connected to your changes to the Mockito code.
5. I removed the Optionals around the NumberFormats because they serve no purpose. The code is the exact same without them: you assign, you check for existence, you use.
6. Given the point under #4, it turns out the special code for the BIGINT case in ResultSetHelperService.getColumnValue() was unnecessary. As a result, your two applyFormatter() methods condensed down to one without generics.
Please take a look and let me know what you think.
Hello Andrew,
I'm afraid this is taking more trouble than it was intended ... I'm sorry for that.
Also, for some reason, I cannot see you commit on the merge request (in fact I neither can see mine anymore), I'll check again later, and complete my answer as needed.
I understand your concerns, but as for my understanding it all ends on the inconsistencies with the mock for the wasNull method, as mentioned earlier. I explain: I made the change in the boolean test because it was not reflecting the reality of the behaviour of the code, in fact, for this test the mock of wasNull is returning false when it should return true. I think this may be also the case for the BigInt type. Also keep in mind that at the end of the getColumnValue function there is a check for null values and returns an empty string. As for my understanding this is the common behaviour for all column types.
Please notice that the change on the boolean test had nothing to do with the extraction of the boolean conversion code to the handleBoolean function, you can check that if you keep the changes in the resultset mock the test will fail with or without this change.
For points 5 and 6 It's ok for me. I prefer Optionals over null values, but I understand is a matter of personal preference.
finally, I attach a test code using h2 in memory database an the latest stable version of opencsv (5.5.2) as a proof of my comments about the boolean and bigint:
You can execute it and see that both null values are rendered as empty strings:
"ID","BOOL_VALUE","BIGINT_VALUE"
"1","true","10000000000"
"2","",""
Let me repeat that back to you in one sentence to see if I got it right: you're telling me the mock we had was not accurately mocking the true behavior of a ResultSet. Is that correct?
Yes, that is.
Then what we really ought to be doing is replacing the mock with an h2 database as you did in your example. Then we can take a look at the tests again.
It seems to me that it has gone too far away from the original intend and scope of this collaboration to this project.
IMHO, I don't think is a good idea to use a concrete implementation of a database in unit tests, I think it's better to mock the expected behaviour, as it is now, beside this edge case I detected.
Also, the change you are proposing is a huge refactor that I don't have the time or the will to achive.
So, I deeply thought about it all and I decided to change my strategy: I have rewitten my tests to work with the ResultSet mock both as it is and with my original fix for it. I will make a new Merge Request with just this change, and a different one for fixing the mock, and close this one.
Please fell free to merge any of them if you think is ok.
Thanks for your time.