I’m using ColdBox v6 and Testbox v4. I have a hand...
# testing
d
I’m using ColdBox v6 and Testbox v4. I have a handler that I’m doing some integration tests with. But I want to break out a bit into a private method on the handler. Maybe that should go in a Service instead, but it seems like overkill for this little private method. So how do I test that private method? I really just want to unit test that method on the handler (I think).
a
generally speaking you wouldn't want to test private methods, but there are times where it can be useful.
a
"Testing a private method" is getting hung-up on implementation detail: one should try to test features not methods. A private method is not going to be a feature. It's gonna be some logic that helps the feature work. So test what facet of the feature is defined / represented by the private method's code. Let's say your private method returns true if the date it's given is a working day (not the weekend, not a public holiday). Why do you need a function to do this? Because the endpoint you are working on accepts a request to create an appointment to see a dentist, and the dentist only works during the normal working week. Your tests of the logic the private method provides would be to confirm that • making an appointment on Wednesday returns a 201-CREATED. • making an appointment on Sunday returns a 400-BAD REQUEST. This exercises the logic in the private function, but it does so by testing the feature. Maybe one might conclude that this private function doesn't belong in the controller (it doesn't), and it belongs in a Calendar Service or something. Or maybe it's a Validation Constraint? Then yer promoting it to be a feature of that other service, and it would be appropriate to test it directly. --- That said: don't get hung up on dogma too much. If it's a right pain to test it from the perspective of the feature, just use
makePublic
to test it directly, as @aliaspooryorik suggests. But also stop to think that your feature might be sub-optimally written if that is the case.
If it's an integration test and the private function hits an external service, and the public "feature" method does a bunch of other stuff that you don't want to execute (hits to other external services, or it relies on live data or something); then it's probably a sign that the private method does not belong in that class, instead it belongs in an adapter class that focuses solely on the interaction with the external service, and is separate from your business logic.
d
I appreciate the thoughts on this. The private method really is just helping to build a report URL with the right stuff to insert into a database. There are a few different URLs, but they all have the same basic bits so I just wanted to break that out into its own function instead of repeating it in the main method several times. With that in mind, I have some other integration tests that are testing most of the “feature” but wanted to just test that I get the right URL built when all the bits are passed in. Unit testing that by itself would just be easier than doing it in an integration test. So maybe I am just being lazy, ha.
And really, the fact that it is private wasn’t even the tricky part I was thinking about. I just hadn’t unit tested a function on a handler, so I wasn’t sure the best way to go about that. So say the makePublic() doesn’t exist and the method on the handler is public. How would you unit test that? A unit test on a model extends the BaseModelTest and actually asks what model you’re testing, so that makes unit testing on a Modal easy. Do you just do a createObject() within the test to grab the handler and then test a specific function that way? (Am I overthinking this?)
I’d call this a “helper” function on a handler, really.
a
A handler is just a cfc so as you say, then just do a "non coldbox" unit test. I think that the base model test would work. If you don't add a "model" annotation then you can create it yourself. Not at a computer at the moment but think the above is correct!
d
Ok, I’ll play around with it. It’s just one of those funny situations that seems simple but isn’t clicking for me yet.
a
I don't really do coldbox integration tests so I pretty much only do unit testing :)
I use Cypress for end to testing which also covers testing javascript and responsive layouts etc.
d
Yeah, that is on our list. Since moving to React for our front-end stuff, we need to get to something like that.
a
wanted to just test that I get the right URL built
Legit. But it sounds to me like the logic that builds the URL might be tightly coupled to the code that uses the URL, thus making the url-building trickier to test that it ought to be. However obvs we don't always have time to refactor stuff so that it's nicely decoupled, so legit. Best to have a less-than-perfect testing approach and still have the test, than not have the test at all. So: good work!
d
With testing, I’ve admittedly gotten in the way of myself by trying to perfectly test (and therefore giving up) instead of just testing something that gets a lot of the way there. So I appreciate your last sentence. 😄