How to re-use asserts and/or setup in xBehave tests?

126 views Asked by At

In cases where inputs change some asserts, but almost all others stay the same, how does one re-use assert portions. In my example, one of the inputs would change only the last assert, all others would stay the same.

    "When CreateBidCommand is executed"
        .x(() =>
        {
           _createBidCommand = new CreateBidCommand(_client, _bidYear, _optionNumber,
                _underwritingLicenseFiling, _underwriter, _bidType, _description, _claimsApplicationType);
            _commandDispatcher.Send(_createBidCommand);
        });
    "Then Bid should be created"
        .x(() =>
        {
            _bid = _bidRepository.FindByBidNumber(_client, _bidYear, _optionNumber);
            Assert.NotNull(_bid);
        });
    "  with description"
        .x(() => Assert.Equal(_bid.Description, _description));
    "  with Client"
        .x(() => Assert.Equal(_client.Id, _bid.Client.Id));
    "  with OptionNumber"
        .x(() => Assert.Equal(_bid.OptionNumber, _optionNumber));
    "  with BidType"
        .x(() => { Assert.Equal(_bid.BidType.Code, _bidType.Code); });
    "  with ClaimsApplicationType "
        .x(() => Assert.Equal(_bid.ClaimsApplicationType.Code, _claimsApplicationType.Code));
    "  with RegulatoryBody"
        .x(() => Assert.Equal(_bid.RegulatoryBody,_underwritingLicenseFiling.RegulatoryBody));
    "  with Underwriter"
        .x(() => Assert.Equal(_bid.Underwriter,  _underwriter));
    "  with UnderwritingFirm"
        .x(() => Assert.Equal(_bid.UnderwritingFirm,_underwritingLicenseFiling.UnderwritingFirm));
    "Then one and only one BidProposal should be created"
        .x(() => Assert.True(_bid.BidProposals().Count() == 1));
    "  with BaseForm"
        .x(() => Assert.Equal(_underwritingLicenseFiling.BaseForm, _bid.LatestProposal().BaseForm));
    "Then one and only one ClientPolicy should be created"
        .x(() =>
        {
            var clientPolicies = _clientPolicyRepository.FindByBidId(_bid.Id);
            Assert.Equal(clientPolicies.Count(), 1);
        });
    "Then ProductionSchedule should have only one step"
        .x(() => Assert.True(_bid.LatestProposal().ProductionSchedule.Count() == 1));
    "  and it should be Initial creation"
        .x(() =>
                Assert.True(_bid.LatestProposal().ProductionSchedule.ElementAt(0).BidStatusType.Code ==
                            BidStatusTypeCode.InitialCreation));
2

There are 2 answers

0
Lunivore On

Your disparate fields make it very hard to condense these into something meaningful and readable. Consider introducing something which you can then use to match against the created bid. You could use a builder pattern to create this easily with any fields required. For instance:

// (Type declared here just to make it obvious)
FakeBid _expectedBid = new FakeBidBuilder().WithClient(_client)
                                   .WithBidYear(_bidYear)
                                   // etc.
                                   .Build();

With builders, you can also easily set up defaults, so only exceptional or meaningful data really needs to be set up visibly here.

When you call the command, you can now pass it the parameters from this fake bid:

_createBidCommand = new CreateBidCommand(
        _expectedBid.Client,
        _expectedBid.BidYear,
        // etc.
        );

And now you put the matcher on the FakeBid class:

AssertTrue(_expectedBid.Matches(_bid));

Any exceptional checks can be verified separately.

If there's something particular about some different ways that the bid matching works, have a conversation with the business or a representative to find out how they talk about the bids and what they mean, and see if you can capture that language in the different builders and class names.

Remember also that if two different aspects of your bid creation are valuable to two different stakeholders, they should probably be separated into different examples, so it's easier to see why they are the way they are.

The primary reason for having class-level examples / tests like this isn't to catch bugs or test the code; it's to enforce clean design and provide living documentation for anyone else who comes along and wants to understand what the code does and why it's valuable. Hope these patterns give you some ideas.

0
Adam Ralph On

I would do this by creating a testing DSL which does standard assertions for me, e.g.

    "When CreateBidCommand is executed"
        .x(() =>
        {
           _createBidCommand = new CreateBidCommand(_client, _bidYear, _optionNumber,
                _underwritingLicenseFiling, _underwriter, _bidType, _description, _claimsApplicationType);
            _commandDispatcher.Send(_createBidCommand);
        });
    "Then Bid should be created"
        .x(() =>
        {
            _bid = _bidRepository.FindByBidNumber(_client, _bidYear, _optionNumber);
            Assert.NotNull(_bid);
        });
    "And the bid should have the properties descibed by the command"
        .x(() => AssertBid(_bid, _description, _client, ... ));
    ...

Where AssertBid is a method in my testing DSL.