Reputation: 35
I am new to unit testing. I am trying to test something very simple:
[HttpPost]
public ActionResult EditProfile(ProfileViewModel model)
{
if (ModelState.IsValid)
{
// Retrieve current user
var userId = User.Identity.GetUserId();
var user = _dataRepository.GetUserById(userId);
//If it isn't the single-instance default picture, delete the current profile
// picture from the Profile_Pictures folder
if (!String.Equals(user.ProfilePictureUrl, _defaultPic))
System.IO.File.Delete(Server.MapPath(user.ProfilePictureUrl));
In this section of code, I am creating a condition where this line will evaluate as true:
if (!String.Equals(user.ProfilePictureUrl, _defaultPic))
I would like to verify that System.IO.File.Delete
is called.
What is the best way to do this?
Do I need to refactor by wrapping the System.IO.File.Delete
call in my own class that implements an interface so that I can mock it and verify that it was called?
I am using Moq.
Upvotes: 3
Views: 1040
Reputation: 247098
Do I need to refactor by wrapping the System.IO.File.Delete call in my own class that implements an interface so that I can mock it and verify that it was called?
Yes
Encapsulate the implementation concerns
public interface IFileSystem {
void Delete(string path);
//...code removed for brevity
}
public class ServerFileSystemWrapper : IFileSystem {
public void Delete(string path) {
System.IO.File.Delete(Server.MapPath(path));
}
//...code removed for brevity
}
Which would be explicitly injected into dependents via constructor injection and used.
if (!String.Equals(user.ProfilePictureUrl, _defaultPic))
_fileSystem.Delete(user.ProfilePictureUrl); //IFileSystem.Delete(string path)
This would now allow mocks to be setup and verified as needed
//Arrange
var mockFile = new Mock<IFileSystem>();
var profilePictureUrl = "...";
//...code removed for brevity
var sut = new AccountController(mockFile.Object, ....);
//Act
var result = sut.EditProfile(model);
//Assert
result.Should().NotBeNull();
mockFile.Verify(_ => _.Delete(profilePictureUrl), Times.AtLeastOnce());
Upvotes: 2