[Testbox 4.5.0] How Do You Unit Test a Quick Entity?

I’m trying to design some unit tests for a Quick entity. However, I know that TestBox doesn’t automatically inject dependencies as Wirebox does, so I assume I have to use MockBox to “create” each dependency and inject it into the model we want to test.

Quick entities have a ton of dependencies, including Str, QuickBuilder, Wirebox, and more. Mocking each of these (and each of their dependencies) feels like it would be a rabbit hole of pain. Is there a better way to handle unit tests for Quick entities?

Sample code:

it( "can return a memento", function(){
    expect( model.getMemento() ).toBeStruct(); // throws:  Element _STR is undefined in a Java object of type class [Ljava.lang.String;.

Note: I know there are integration tests that simulate a real request, so you can take advantage of Wirebox and dependency injection. However, it feels like a code smell to me to have to create a bunch of new handlers for every single model AND more importantly, you can’t use Mockbox to modify objects in an integration test.

Note: I looked at the docs for TestBox/MockBox and couldn’t see anything that covers this topic other than how to create mock objects/stubs. I also checked CFCasts since it’s a great resource for tutorials, but a search for “MockBox” yielded 0 results.

Using ColdBox’s BaseTestCase does not mean you have to use execute or request (or get, post, etc.). You can use the BaseTestCase and then use WireBox to create the Quick entity for you. Then you can also use MockBox (if needed) on the created entity. To me, this is still a unit test since the Quick entity is one unit. (If other people disagree, sure. ¯_(ツ)_/¯ Tests exist for me to be confident, not to check some box.)

I’d also be curious what exactly you are looking to unit test in Quick. I know I occasionally have tests for things like a custom formatter for a date string (for instance, I had one entity that included a time zone in the database), but I usually tend toward hitting the database. This is because testing that a scope exists isn’t really helpful: 1) I can still mess up the SQL in the scope and 2) whether I use 0, 1, or 4 scopes in a query is really an implementation detail.

Anyway, you test what makes sense for you, but I would still use BaseTestCase for these unit tests. :+1:t2:

1 Like

Rock solid, @elpete! I hadn’t considered extending BaseTestCase. I always have segregated integration and unit tests in my brain, but your logic makes perfect sense.

The example in my initial post was oversimplified for brevity. My goal is to perform some unit tests on an API wrapper I built. Unfortunately, the API provider isn’t always consistent with how it returns data, so I want to write tests to account for all the various types of responses the wrapper could have to deal with.

Some API wrapper methods require an entity to be passed as an argument, and the wrapper performs some behavior on the entity (like getMemento()). Rather than mocking all of the cool stuff Quick does, I figured it would be easier to pass in an actual Entity and then mock the API wrapper methods as needed.

Aside from the API wrapper tests, I also want to start writing unit tests on my Quick entities individually. I’m trying to add more “behavior” to my entities rather than thinking of them as “bags of data.” For example, an Order Entity might have a method called emailReceipt() which would send a detailed order receipt to a customer using cbMailServices and update the status of the Order. Having a live Quick entity feels like a better approach than mocking everything from scratch.

Finally, one of the things I struggle with as a developer is determining when I’ve made an entity “do too much” and should instead break it down into smaller components. My hope is that unit tests may be a good way to get a bird’s eye view of a particular entity, and help evaluate if I’ve made something too bloated or not.

Thanks as always for your guidance! I appreciate it!