When unit testing the result and/or side effects from a single logical action, how do you keep the code DRY? Take the following example written in Jasmine:
describe("frobnicate", function () {
var foo;
beforeEach(function () {
foo = getFoo();
});
it("causes side-effect 1", function () {
frobnicate(foo);
expect(sideEffect1).toEqual('you did it');
});
it("causes side-effect 2", function () {
frobnicate(foo);
expect(sideEffect2).toHaveBeenCalled();
});
/* side effect 3, 4, etc. */
});
Notice the repeated Act with the calls to frobnicate(foo)
. With a unit testing framework that allows for nested describe contexts (such as Jasmine), it seems very natural to refactor the tests along the lines of:
describe("frobnicate", function () {
beforeEach(function () {
var foo = getFoo();
frobnicate(foo);
});
it("causes side-effect 1", function () {
expect(sideEffect1).toEqual('you did it');
});
it("causes side-effect 2", function () {
expect(sideEffect2).toHaveBeenCalled();
});
/* test side effect 3, 4, etc. */
});
Is this style in any way contradictory to the AAA testing style? Does refactoring the code this way invite other problems?
Not only is this not-contradictory to Arrange-Act-Assert but I would insist you do do it this way. Duplication in tests is one of the major maintenance problems and removal should be done as much as possible.
The biggest question to ask on duplication is "what would happen if this changes?", if you have to change it in multiple places, refactor.