Home > OS >  Implement a list of interfaces during Unit Test using NUnit
Implement a list of interfaces during Unit Test using NUnit

Time:05-24

I'm currently studying C# and I'm quiet stunned over a simple task. I have this code to test:

    public interface IAppointment
{
    public string PatientName { get; set; }
    public IEnumerable<DateTime> ProposedTimes { get; set; }
    public DateTime? SelectedAppointmentTime { set; }
}

public static class MedicalScheduler
{
    public static Dictionary<DateTime, string> Appointments { get; set; } = new Dictionary<DateTime, string>();
    public static List<DateTime> FreeSlots { get; set; } = new List<DateTime>();

    public static IEnumerable<Tuple<string, bool>> Schedule(IEnumerable<IAppointment> requests)
    {
        bool slotFound = false;
        foreach (var appointment in requests)
        {
            if (slotFound) continue;

            foreach (var times in appointment.ProposedTimes)
            {
                var freeSlot = FreeSlots.Where(s => s.Date == times.Date).FirstOrDefault();

                if (freeSlot != null)
                {
                    slotFound = true;
                    Appointments.Remove(freeSlot);
                    appointment.SelectedAppointmentTime = freeSlot;
                    yield return new Tuple<string, bool>(appointment.PatientName, true);
                }
            }

            yield return new Tuple<string, bool>(appointment.PatientName, false);
        }
    }
}

And I'm required to test "Schedule" with a certain set of parameters. For example, I need to test it with empty Appointments and FreeList but with a single element in "requests". I think I have understood how to compile a Unit Test and to set the Dictionary and List parameters. But I'm not sure how to create the IEnumerable variable. My idea was to create a List of IAppointment(s), but how can I implement the interface in the test unit? I have tried using Moq but I didn't understood how I should use it correctly.

I'm sorry if the request seems quite confusing, but I don't know how to explain better :)

Thanks in advance for the help.

CodePudding user response:

Please see the following example:

[Test]
public void Schedule()
{
    // Arrange
    var appointmentMock = new Mock<IAppointment>();
    appointmentMock.Setup(appointment => appointment.PatientName).Returns("Dixie Dörner");
    appointmentMock.Setup(appointment => appointment.ProposedTimes).Returns(
        new List<DateTime>
        {
            new DateTime(1953,4,12), 
            new DateTime(1953,4,13)
        });
    var requests = new List<IAppointment>{appointmentMock.Object};

    // Act
    var results = MedicalScheduler.Schedule(requests);

    // Assert
    Assert.IsTrue(results.Any());
    // results.Should().HaveCount(1); // If you're using FluentAssertions
}

MedicalScheduler.Schedule accepts any parameter implementing IEnumerable<IAppointment>, e. g. List<IAppointment> or Collection<IAppointment>.

So you simply create a List<IAppointment> and fill it with custom instances of IAppointment.

You can use Moq for creating the instances, as I did in the example. But for my own projects, I prefer the builder pattern:

internal static class AppointmentBuilder
{
    public static IAppointment CreateDefault() => new Appointment();

    public static IAppointment WithPatientName(this IAppointment appointment, string patientName)
    {
        appointment.PatientName = patientName;
        return appointment;
    }
    
    public static IAppointment WithProposedTimes(this IAppointment appointment, params DateTime[] proposedTimes)
    {
        appointment.ProposedTimes = proposedTimes;
        return appointment;
    }
    
    private class Appointment : IAppointment
    {
        public string PatientName { get; set; }
        public IEnumerable<DateTime> ProposedTimes { get; set; }
        public DateTime? SelectedAppointmentTime { get; set; }
    }
}

[Test]
public void Schedule()
{
    // Arrange
    var requests = new List<IAppointment>{AppointmentBuilder.CreateDefault()
        .WithPatientName("Dixie")
        .WithProposedTimes(new DateTime(1953,4,12))};

    // Act
    var results = MedicalScheduler.Schedule(requests);

    // Assert
    Assert.IsTrue(results.Any());
    // results.Should().HaveCount(1); // If you're using FluentAssertions
}
  • Related