7

I'm developing an application that relies heavily on Joda-Money, and have a number of unit tests that verify my business logic. One (admittedly minor) sticking point for me has been what sort of Money/BigMoney objects to test with; specifically, what CurrencyUnit to use.

As I see it, I have a couple of options:

  • Just use USD

    This is clearly the easiest way to go, and most of my actual application will be working with US Dollars so it makes a fair bit of sense. On the other hand, it feels rather US-centric, and I'm concerned it would risk letting currency-specific errors go unchecked.

  • Use another real currency, like CAD

    This would catch erroneous hard-codings of USD, but otherwise isn't much better than just using USD.

  • Use a dedicated "fake" currency, i.e. XTS

    This clearly makes sense, after all, XTS is "reserved for use in testing". But Joda denotes psuedo-currencies as currencies with -1 decimal places. In practice, the primary difference between currencies in Joda-Money is the number of decimal places, so this risks masking any errors involving decimal place precision, such as erroneously rounding to an integer value.

  • Register my own custom currency with CurrencyUnit.registerCurrency()

    This would obviously work, but seems a little odd seeing as there are alternatives.

  • Use a CurrencyUnit instance created by a mocking library

    Pretty much the same as registering a custom currency.

Again, this is obviously a minor issue, but I'm curious if there's a standard practice for cases like this, or if there's a clear reason to prefer one of these options in particular.

Community
  • 1
  • 1
dimo414
  • 47,227
  • 18
  • 148
  • 244
  • This doesn't seem minor to me. You are about to spread this decision all over your unit tests right? If you can't make this decision exist in only one place then you're about to be stuck with it forever. – candied_orange Mar 12 '15 at 02:42
  • @CandiedOrange agreed, but I've had other questions get showered with "why are you even wasting your time on this?!?!?!?!?!" responses, so calling all of my curiosities "minor" concerns is a bit of a defense mechanism. – dimo414 Mar 12 '15 at 02:46
  • 2
    Haters gonna hate. Keep asking, stay upbeat, and the love will find you. Peace. – candied_orange Mar 12 '15 at 02:48

2 Answers2

4

Use USD (or, generally, whatever currency is most commonly used in your application). I say this for two reasons:

  • Good test data is unremarkable in every respect except that part of it which the test is actually about. When you're writing tests that don't have anything to do with differences between currencies, you don't want to have to think about differences between currencies. Just use whatever is most natural in the application.

  • The idea that using an unusual currency everywhere will somehow result in better testing of unusual currencies is a red herring. Tests should be explicit and focused. If you need to test something about a specific currency, write a test whose point is to test that thing. And if a test is not about a specific currency, it shouldn't break when handling of some unusual aspect of that currency breaks -- it's not valuable to have half your tests break for the same reason; you only want one to break. So there is just no need to spread unusual currencies around the test suite and hope that that will catch something. Instead, optimize for readability; see point 1.

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
  • 1
    Thanks, that rational rings pretty true to me. If I'm writing any code that is explicitly currency-dependent, I should be testing it in multiple currencies, not relying on the testing framework to introduce edge-cases for me. – dimo414 Mar 12 '15 at 02:43
0

Since most of your application deals with U. S. dollars, it makes sense to use them for the vast majority of your tests. What currency-specific errors are you worried might happen? Missing halfpennies when compounding interest? Conversion to yen and back is off by a cent or two? Write tests for that.

If I were you, I'd fire up a local REPL (a Scala REPL works very well if you don't have JShell), run a few experiments. You'll probably find that you worried for nothing. Or you might discover that there is indeed a flaw, and your REPL session will inform how you write a test for that flaw.

You're using Joda Money because you don't want to reinvent this particular wheel. I didn't realize that until I read the question details. Presumably Joda Money has been tested rigorously by its developers and it does everything you expect it to do. You don't need to test it again.

But if you were making your own class to represent money amounts, I would suggest you use U. S. dollars, euros, Japanese yen and Lybian dinars (LYD). The reason for the first three is obvious. I suggest Lybian dinars because of the three decimal places. From what I can gather, there is no physical 1 dirham coin, so, for example, 513 darahim would get rounded down to 500 darahim and 997 darahim would get rounded up to a full dinar.

To test conversions, I would start with East Caribbean dollars (XCD), since they are fixed to exchange to US$2.70. Later on you can worry about currencies that fluctuate in relation to each other, and whether you're going to deal with them by mocking a rate server, or by connecting to an actual rate server but putting variances in your tests or by some other way.

Alonso del Arte
  • 1,005
  • 1
  • 8
  • 19
  • As I discussed in the question, using USD in tests risks masking bugs in the code under test, such as erroneously hard-coding USD somewhere that should have taken a currency as input. Similarly you could imagine code (again, erroneously) hard-coding division by 100 cents, which will work correctly in any test that uses USD but will fail in production if some different currency is used. The intent is not to test Joda Money itself but the implementation of code *using* Joda Money. – dimo414 Sep 27 '20 at 21:49
  • If you subscribe to the TDD philosophy (not too dogmatically, I hope) then such problems would be addressed by new tests if not during refactoring for previous tests. And doesn't Joda Money have a convenient function for subdivisions? In `java.util.Currency` there's `getDefaultFractionDigits()`, but it's not as helpful with the Madagascar ariary (MGA). – Alonso del Arte Sep 27 '20 at 22:24