About Unit Testing for C# Developers

In one of the sections I encountered a problem, this one:

  public string GetUnprocessedVideosAsCsvRefactoredVersion()
    {
        var videoIds = new List<int>();

        var videos = _videoRepository.GetUnprocessedVideos();

            foreach (var v in videos)
                videoIds.Add(v.Id);

            return String.Join(",", videoIds);
    }

In VideoRepository class, we know that only videos whose isProcessed variable is false should be added to the list. But the unit test written by Mosh does not work, meaning that the logic behind it is wrong. Am I right? Can you enlighten me please?
I mean if we initialize a list like this:

  var videos = new List<Video>()
        {
            new Video{Id = 1, Title= "Shrek", IsProcessed = false},
            new Video{Id = 2, Title= "StarWars", IsProcessed = false},
            new Video{Id = 3, Title= "Separation", IsProcessed = true},
            new Video{Id = 4, Title= "PulpFiction", IsProcessed = false},
            new Video{Id = 5, Title= "FightClub", IsProcessed = false},
            new Video{Id = 6, Title= "Fountain", IsProcessed = true},
        };

The method should only filter 1,2,4, and 5 but it returns all of them.

Hi,

From what I understand you are right stating only videos with Ids 1,2,4 and 5 should be returned.

Now where is Mosh unit test ?

	public static void Main()
	{
		  var videos = new List<Video>()
        {
            new Video{Id = 1, Title= "Shrek", IsProcessed = false},
            new Video{Id = 2, Title= "StarWars", IsProcessed = false},
            new Video{Id = 3, Title= "Separation", IsProcessed = true},
            new Video{Id = 4, Title= "PulpFiction", IsProcessed = false},
            new Video{Id = 5, Title= "FightClub", IsProcessed = false},
            new Video{Id = 6, Title= "Fountain", IsProcessed = true},
        };
		
		var _videoRepo = new VideoRepository();
		
		var result = _videoRepo.GetUnprocessedVideos(videos);
		
		result.ForEach(Console.WriteLine);
	}

	public class Video 
	{
		public int Id {get;set;}
		public string Title {get;set;}
		public bool IsProcessed {get;set;}
		
		public override string ToString() 
		{
			return Id+" "+Title+" "+((IsProcessed)?"Processed":"Not Processed");
		}
	}
	
	public class VideoRepository
	{
		public List<Video> GetUnprocessedVideos(List<Video> videos)
		{
			return videos.Where(v => !v.IsProcessed).ToList();
		}
	}

Output

1 Shrek Not Processed
2 StarWars Not Processed
4 PulpFiction Not Processed
5 FightClub Not Processed

Hi,
Thank you for replying.

This is the GetUnprocessedVideos method written by Mosh. I was supposed to write a unit test around it.

   public IEnumerable<Video> GetUnprocessedVideos()
        {
            using (var context = new VideoContext())
            {
                var videos =
                   (from video in context.Videos
                    where !video.IsProcessed
                    select video).ToList();
                return videos;
            }
        }

This is the test I wrote. I believe that this should pass but it does not. It says that it returns 1,2,3,4,5,6 but as far as I understood, that is not what the method should be doing. The method should filter videos whose IsProcessed property is set to false.

  public void GetUnprocessedVideosAsCsvRefactoredVersion_SomeVideosAreNotProcessed_ReturnsACommaSeparatedStringOfIds()
        {
            var videos = new List<Video>()
            {
                new Video{Id = 1, Title= "Shrek", IsProcessed = false},
                new Video{Id = 2, Title= "StarWars", IsProcessed = false},
                new Video{Id = 3, Title= "Separation", IsProcessed = true},
                new Video{Id = 4, Title= "PulpFiction", IsProcessed = false},
                new Video{Id = 5, Title= "FightClub", IsProcessed = false},
                new Video{Id = 6, Title= "Fountain", IsProcessed = true},
            };

            // Arrange
            var mockFileReader = new Mock<IFileReader>();
            var mockVideoRepository = new Mock<IVideoRepository>();
            mockVideoRepository.Setup(vr => vr.GetUnprocessedVideos()).Returns(videos);
            var videoService = new VideoService(mockVideoRepository.Object, mockFileReader.Object);

            // Act
            var result = videoService.GetUnprocessedVideosAsCsvRefactoredVersion();

            // Assert
            Assert.That(result, Is.EqualTo("1,2,4,5"));
        }

Mosh wrote the test like this in his video, ignoring the rest of the properties.

        public void GetUnprocessedVideosAsCsvRefactoredVersion_SomeVideosAreNotProcessed_ReturnsACommaSeparatedStringOfIds()
        {
            var videos = new List<Video>()
            {
                new Video{Id = 1},
                new Video{Id = 2},
                new Video{Id = 3},
                new Video{Id = 4},
                new Video{Id = 5},
                new Video{Id = 6},
            };

            // Arrange
            var mockFileReader = new Mock<IFileReader>();
            var mockVideoRepository = new Mock<IVideoRepository>();
            mockVideoRepository.Setup(vr => vr.GetUnprocessedVideos()).Returns(videos);
            var videoService = new VideoService(mockVideoRepository.Object, mockFileReader.Object);

            // Act
            var result = videoService.GetUnprocessedVideosAsCsvRefactoredVersion();

            // Assert
            Assert.That(result, Is.EqualTo("1,2,3,4,5,6"));
        }

Hi,
I see that unlike my simplified example you are actually using EF to contact an actual DB with query syntax.

I am using NUnit quite regularly at work though I am far from being an expert. But I would not check a set of values this way. Simply because I would never think a string would work here.
I expect an IEnumerable<Video> which is an object.

So say we want to check the presence of those expected entries by their Id property,
I would do any of this

Assert.Multiple(() =>{
   Assert.That(result.Any(v => v.Id == 1), Is.True);
   Assert.That(result.Any(v => v.Id == 2), Is.True);
   Assert.That(result.Any(v => v.Id == 3), Is.False);
   Assert.That(result.Any(v => v.Id == 4), Is.True);
   Assert.That(result.Any(v => v.Id == 5), Is.True);
   Assert.That(result.Any(v => v.Id == 6), Is.False);
});

Now a shorter thing would be to simply check if any item has an undesired value which is simply check if any item has IsProcessed set to True. In the above snippet (from previous comment) I just did quickly try this.

var essai1 = videos.Any(v => v.Id == 1);
var essai2 = videos.Any(v => v.IsProcessed);
var essai3 = result.Any(v => v.Id == 1);
var essai4 = result.Any(v => v.IsProcessed);

Console.WriteLine("Results "+essai1+" "+essai2+" "+essai3+" "+essai4);

Output

Results True True True False

So in NUnit test you could just try this

   Assert.That(result.Any(v => v.IsProcessed), Is.False);

Just a note: the word filter is a bit unclear. It is a bit like the word evolution (at least in French).
Evolution can be either raise or fall. Many people use it when things raise but that’s not necessarily the case and it can be confusing.

Filter is a bit of the same idea. You can filter to keep or remove. The name of the method GetUnprocessedVideos gives us a hint on which side we are but please be careful.

Hope this helps.

Cheers.

Thank you for the clarification. May the force be with you.