A class
has a trait
.
The class
is expected to call a function provided by the trait
during a certain method
invocation.
How do I write a unit test
to ensure that that happens?
The difficulty, to me, comes from the fact that a trait
is part of the class definition
, so I cannot mock the trait in the test, as I could if the trait
was instead an object
that was passed in to the class
constructor.
What does the trait do? If the trait changes state, then check that the state was properly changed. If the trait fetches some data, make sure it is fetched and processed correctly.
Your unit is the method itself, not the trait it depends on. Treat the trait as an implementation detail of the method, since that’s what it is.
For our purposes, this is the same question as:
Assume I have two classes
A
andB
:abstract class A: method foo: 42; virtual method bar; class B extends A: method bar: self.foo() + 4;
How can I unit-test class
B
, considering that I cannot mockA
?
If the language you are using is sufficiently dynamic, you could actually replace the A
type with a mocked class. If the language treats types as first class objects, you could do a form of dependency injection. Otherwise, you could still use conditional compilation to switch between actual A
for production and integration tests and a mock A'
for unit testing – but that is prone to hide or even create bugs.
But quite frankly, this complexity seems silly to me. I’d rather write a suite of general unit tests for the supertype A
, which get inherited for every type B
that somehow extends, does or implements A
. Because A
itself cannot be instantiated, it can be tested by a mock B'
. After that, I’d test the other subtypes of A
both with the A test suite, and their individual tests.
Yes, you can argue that this is a bit of an integration test rather than an unit test. However, it would be wise to treat the whole type with all inherited stuff and all traits composed into it as your unit, in contrast to just the parts you newly added in this class.
IMO understanding the UNIT in the unit-testing will provide more light in your case
A class has a trait
The trait is not an object
You need to test this class
To unit test this class the public capabilities of the class are what you need to test
As this is what is promised by the class implementation
This forms the unit in the unit level tests
Essentially it means if the trait of that class
1> Can be public property (promised as a contract by the class)
2> Can be private property (not promised to external world but used solely for internal purpose)
In Case of 1> ie public property
You need to assert the property holds state info as expected by the author in various scenarios, so write tests for the same
In Case of 2> ie private property
IMO it doesnt need tests.
If all public methods, contracts as promised by the class is Asserted to work as expected in all scenarios, i think you should be well covered.
You deliver what you promised to deliver in all scenarios as expected.