2

I have these lines in multiple test methods. Now, trying to create a private method to clean up but not sure how to do it. Any suggestion or pointer would be really helpful. Thanks.

    var actualValiationString = string.Empty;
    void messageBuilder(string validationString)
        => actualValiationString = validationString;
    var validationDelegate = new Action<string>(messageBuilder);

Here's the real test methods look like:

[Theory]
[MemberData(nameof(TryGetBoolTestData))]
public void TryGetBoolShouldReturnBool(
    Dictionary<string,string> metadata,
    bool expectedValue,
    string expectedValidationString
)
{
    var actualValiationString = string.Empty;
    void messageBuilder(string validationString)
        => actualValiationString = validationString;
    var validationDelegate = new Action<string>(messageBuilder);


    DictionaryExtensions.TryGetBool(
        metadata,
        MetadataKey,
        out var response,
        validationDelegate
    );


    response.Should().Be(expectedValue);
    actualValiationString.Should().Be(expectedValidationString);
}

[Theory]
[MemberData(nameof(GetBoolTestDataWithDefaultValueAndAction))]
public void GetBoolWithDefaultValueAndActionShouldReturnBool(
    Dictionary<string, string> metadata,
    bool defaultValue,
    bool expectedValue,
    string expectedValidateString
)
{
    var actualValiationString = string.Empty;
    void messageBuilder(string validationString)
        => actualValiationString = validationString;
    var validationDelegate = new Action<string>(messageBuilder);


    var actualValue = DictionaryExtensions.GetBool
    (
        metadata,
        MetadataKey,
        defaultValue,
        validationDelegate
    );


    actualValue.Should().Be(expectedValue);
    actualValiationString.Should().Be(expectedValidateString);
}
2
  • 2
    Show us your attempts at solving this.
    – Flater
    Mar 1, 2023 at 3:47
  • I don't think explicitly creating a delegate is needed; just pass the local function directly. Or write it as a lambda inline. Then the code overhead is lower. Mar 1, 2023 at 10:33

1 Answer 1

5

Bundle the delegate and the local variable in a class:

class Validator
{
    public string ActualValidationString { get; private set; } = string.Empty;
    public void Validation(string msg)
    {
        ActualValidationString = msg;
    }
}

Now you can use it this way:

var validator = new Validator();

var actualValue = DictionaryExtensions.GetBool
(
    metadata,
    MetadataKey,
    defaultValue,
    validator.Validation
);


actualValue.Should().Be(expectedValue);
validator.ActualValidationString.Should().Be(expectedValidateString);

Using a class is probably the most idiomatic solution in C#. But if you really insist in a "single private method", one can also implement this in terms of two closures sharing a common variable:

 static (Action<string>, Func<string>) CreateValidator()
 {
     string actualString=string.Empty;
     return (s => actualString=s , () => { return actualString;});
 }

This has to be used this way:

var validator = CreateValidator();

var actualValue = DictionaryExtensions.GetBool
(
    metadata,
    MetadataKey,
    defaultValue,
    validator.Item1
);

actualValue.Should().Be(expectedValue);
validator.Item2().Should().Be(expectedValidateString);

This solution is a little shorter than the first one, but may - argueably - a little bit harder to grasp if one isn't used to functional programming.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.