0

I have a best practice question.

When using a selector layer pattern, what does the community think is the best practice around testing? I kind of hate writing a test for no reason other than to test a query, and if your integration tests are being done, you will get coverage from them.

But if you need to deploy an updated selector class quickly, you must run all the associated integration tests to get it into prod. What does everyone think the correct method is here?

1
  • 1
    I don't understand who's downvoting best practice questions around this site Commented Mar 16, 2023 at 15:28

2 Answers 2

2

My selector classes (fflib - and I have a lot of them), all have a corresponding testmethod.

Three reasons

  • Classes should have unit tests, period.
  • Classes with unit tests can be deployed efficiently without having to run all tests
  • Selector class methods actually have logic - they take in arguments like ContactsSelector.newInstance().selectByEmail(Set<String> emails) so you need to mock real Contacts with different emails and verify that only the matching Contacts by email are fetched

Yes, it is tedious but I sleep better at night knowing I didn't take shortcuts

Update

It is worth mentioning that selector classes have two huge advantages

  • Reusability across the code base
  • They can be mocked in unit tests - thus saving the need to do DML setup. Mocking is also the only solution when the underlying objects can't be setup with DML (like AsyncApexJob)

Hence, given these advantages, writing unit tests is even more worthwhile

1
  • Great point. I think I was hoping someone would say that when it comes to reading from the database it is ok to be lazy. Commented Mar 17, 2023 at 10:15
1

I don't think there's any difference in best practice here (compared to best practice in testing anything else).

That is to say, your goal here is still to execute code (to gain coverage for it) and to assert that the results from executing that code match your expectations. The results you have here are:

  • The number of records returned
  • The fields and related (child or parent) data that is included

That first item is perhaps not so useful, but the second item is. That's a good enough basis for a dedicated unit test in my books. getPopulatedFieldsAsMap() and .getSObject() would be helpful for making assertions against returned fields.

3
  • Part of me feels like this just creates pointless Database IO operations and slow tests. When I look at the sample code for Andrew Fawcetts book there are no tests for the selector classes. Maybe an oversight, but I always go back and forth on this. github.com/PacktPublishing/… Commented Mar 16, 2023 at 16:27
  • 1
    @BrooksJohnson A small price to pay for the benefit of not needing to perform DML to set up test data in your other unit tests (though I'd still use DML to set up test data in integration tests just to be sure things work). I've found that we can't remove complexity in software beyond a certain point, we can just move it around. This is simply moving that detail of other unit tests to this set of unit tests, and although tests with DML take longer, it'll still almost certainly be faster than identifying and running all of the relevant integration tests.
    – Derek F
    Commented Mar 16, 2023 at 16:59
  • Great point. It is clearly a pain. I was hoping someone would give me permission not to do it. Commented Mar 17, 2023 at 10:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .