-1
    foreach (Residency residency in test.Residencies)
        {
            if (residency.TestGuid == testGuid)
            {
                if (requiredResidency == null)
                    requiredResidency = residency;
                else if (requiredResidency.StartDate < residency.StartDate)
                    requiredResidency = residency;
            }
        }

the above loop should be reusable, created a Utilities class not sure on how to call the same function in the test when required. TIA

  • just put the code into a method? What did you try already? – MakePeaceGreatAgain Jul 03 '23 at 09:50
  • yes foreach loop was already added into one of the test method, but this need to be called in some of the methods, instead of pasting the code in each, how can I reuse it? Created a Helpers/utilities class and not sure on next steps.Thanks – user21175930 Jul 03 '23 at 09:54
  • Make an abstract class with this a protected method. Then make the test classes that need to use it derive from that class. That would be the way by inheritance. Then you could make a utility class that you just instantiate (or maybe it could be completely static) where needed. – Fildor Jul 03 '23 at 10:08
  • 1
    The only flaw you need to solve is that this piece of code is based on a side effect. It sets a variable (or field, property, whatever) that is declared outside the scope of this snippet. – Fildor Jul 03 '23 at 10:10
  • ... but I have the feeling, this could be refactored into some LINQ statement ... – Fildor Jul 03 '23 at 10:12
  • 1
    Something like `requiredResidency = requiredResidency is null ? test.Residencies.LastOrDefault(r => r.TestGuid == testGuid) : test.Residencies.LastOrDefault(r => r.TestGuid == testGuid && requiredResidency.StartDate < r.StartDate);` which very probably could be further optimized. – Fildor Jul 03 '23 at 10:16
  • You need to show us more examples. From your code I can't tell which parts are reusable/common and which parts are interchangeable. – Good Night Nerd Pride Jul 03 '23 at 11:27
  • Or wait... are you asking how to [extract](https://refactoring.guru/extract-method) the whole loop into a method? – Good Night Nerd Pride Jul 03 '23 at 11:30
  • yes whole into a method @GoodNightNerdPride, thanks – user21175930 Jul 03 '23 at 11:53

1 Answers1

1

It is unclear, where requiredResidency is declared. That makes it a little hard to give an answer.

Now, what I have seen (and done) in actual projects are these:

Inheritance

Functionality, that is common to a set of tests is drawn into a "TestBase".

Example:

public abstract class ResidencyTestBase
{
    protected Residency GetRequiredResidency( IEnumerable<Residency> testResidencies, Guid testGuid )
    {
         // TODO Implementation
    }
}

// and then you'd have various tests like

public class SomeResidencyTest : ResidencyTestBase
{

    [Fact] // we are using xUnit but the idea applies to other 
           // Test Frameworks, too.
    public void SomeTest()
    {
         var sut = GetRequiredResidency( testData, testId );
// ...
    }
}

public class SomeOtherResidencyTest : ResidencyTestBase
{

    [Fact] // we are using xUnit
    public void SomeOtherTest()
    {
         var sut = GetRequiredResidency( testData, testId );
// ...
    }
}

"TestHelper" class(es)

Example:

public static class ResidencyTestHelper
{
    // maybe as extension method on the test data?
    public static Residency GetRequiredResidency(this IEnumerable<Residency> testData, Guid testId)
    {
        // impl.
    }
}

// Usage
var sut = testData.GetRequiredResidency( testId );

Your specific functionality

foreach (Residency residency in test.Residencies)
{
    if (residency.TestGuid == testGuid) // can be expressed as a LINQ Where
    {
        if (requiredResidency == null)
            requiredResidency = residency; // Sideeffect!
        else if (requiredResidency.StartDate < residency.StartDate)
            requiredResidency = residency;
        // Missing case: both conditions fail ...
    }
}

So, I guess one could refactor this like so:

// As ExtensionMethod:
// We _return_ the reference, because we cannot rely on sideeffects
static Residency? GetRequiredResidency ( this Residency? requiredResidency,
    IEnumerable<Residency> testData, Guid testId )
{
// Linq is used here, but this can also be expressed in plain old syntax
    var residenciesById = testData.Where(r => r.TestGuid == testGuid);
    if( requiredResidency is not null )
        residenciesById = residenciesById.Where(r =>  requiredResidency.StartDate < r.StartDate );
    return residenciesById.LastOrDefault() ?? requiredResidency;
//  ^^ this is to make the behavior the same. If both conditions fail 
//     (= "missing case" in your code, your code does not change the 
//     original, so) we get null here, so we set what it originally was.
}

// Usage
Residency requiredResidency = ...; // Assume declared somewhere...

requiredResidency = requiredResidency.GetRequiredResidency( test.Residencies, testId );
Fildor
  • 14,510
  • 4
  • 35
  • 67
  • Of all possible options for code reuse [inheritance is the worst](https://en.wikipedia.org/wiki/Composition_over_inheritance). – Good Night Nerd Pride Jul 03 '23 at 15:28
  • @GoodNightNerdPride Examples are not in a particular order. I personally prefer the second. But inheritance (if you keep it to one level) can be pretty handy, too, though. – Fildor Jul 10 '23 at 07:08