I wanna test my method with mock but it throw this exception. My class is this (this class do some simple actions on a file as though unzipping the file) :
public class FileActions
{
public virtual void Decompress(FileInfo fileInfo, DirectoryInfo directoryInfo)
{
ZipFile.ExtractToDirectory(fileInfo.FullName, directoryInfo.FullName);
}
public virtual FileInfo GetConvertedFileToZip(FileInfo fileInfo)
{
try
{
var changeExtension = Path.ChangeExtension(fileInfo.FullName, "zip");
File.Move(fileInfo.FullName, changeExtension);
return new FileInfo(changeExtension);
}
catch (Exception)
{
throw new FileNotFoundException();
}
}
}
and this is my test :
public void TestMockedMethodForNotNull()
{
var mock = new Mock<FileActions>();
var fInfo = new FileInfo(#"D:\ZipFiles\elmah.nupkg");
mock.Setup(s => s.GetConvertedFileToZip(fInfo)).Verifiable();
mock.VerifyAll();
}
So, why does it get this Error :
Moq.MockVerificationException: The following setups were not matched:
FileActions2 s => s.GetConvertedFileToZip(D:\ZipFiles\elmah.nupkg)
There are several issues with your Unit Test. I will only highlight the mocking side of things, as it relevant to the question you ask. Also your question has refer to "FileActions2", and I think this
a mistake when you originally add the question.
You Test:
[TestMethod]
public void TestMockedMethodForNotNull()
{
var mock = new Mock<FileActions>();
var fileInfo = new FileInfo(#"D:\ZipFiles\elmah.nupkg");
mock.Setup(s => s.GetConvertedFileToZip(fileInfo)).Verifiable();
mock.VerifyAll();
}
The way you have written this test, Moq won't verify on GetConvertedFileToZip
This test fail fundamentally because Moq cannot provide an override for a virtual method GetConvertedFileToZip. You must create a proxy i,e mock.Object.
If you modify your test in such a way so your SUT (Sysytem Under Test), consumes an instance of the mocked object/proxied object
your verify would work partially (partially means you are heading right direction). Still something else to fix which I have described below.
Assuming your SUT is like below
public class Sut
{
public void Do(FileActions fileActions)
{
var fileInfo = new FileInfo(#"D:\ZipFiles\elmah.nupkg");
var s = fileActions.GetConvertedFileToZip(fileInfo);
}
}
Your Test
[TestMethod]
public void TestMockedMethodForNotNull()
{
var mock = new Mock<FileActions>();
var fileInfo = new FileInfo(#"D:\ZipFiles\elmah.nupkg");
mock.Setup(s => s.GetConvertedFileToZip(fileInfo)).Verifiable();
var sut = new Sut();
sut.Do(mock.Object);
mock.VerifyAll();
}
This would produce an exception. This is because fileInfo you have setup on does not match the verification, when invoke via the Sut.
If you were to modify this test as below, this would succeed
[TestMethod]
public void TestMockedMethodForNotNull()
{
var mock = new Mock<FileActions>();
//var fileInfo = new FileInfo(#"D:\ZipFiles\elmah.nupkg");
mock.Setup(s => s.GetConvertedFileToZip(It.IsAny<FileInfo>())).Verifiable();
var sut = new Sut();
sut.Do(mock.Object);
mock.VerifyAll();
}
Related
I use the System.IO.Abstractions.TestingHelpers to mock FileSystem. In my class, I inject IFileSystem and use the instance to call _fileSystem.File.Exists and _fileSystem.File.Delete. In my test class, I would like to verify that the "Delete" method was called. It's easy by mocking only the IFile, but since I already mocked the FileSystem, I don't want to have to mock the Directory, Path and File on top of it. Is it possible to call something like _fileRepository.FileMock.Verify(x => x.Delete(It.IsAny<string>()))...?
public class Downloader : IDownloader
{
public Downloader(HttpClient httpClient, IFileSystem fileSystem)
{
HttpClient = httpClient;
FileSystem = fileSystem;
}
public async Task DownloadConfigFileAsync(string updatedConfigBaseFolderPath, string configurationFileUrl, string personalAccessToken)
{
var newFilePath = FileSystem.Path.Combine(updatedConfigBaseFolderPath, "subfolder1", "myNewFile.txt");
if (FileSystem.File.Exists(newFilePath))
{
FileSystem.File.Delete(newFilePath);
}
// rest of implementation ommited for demo purpose
}
}
And my test is like :
[Fact]
public async void Given_MissingPathParts_ShouldThrow()
{
var handlerMock = GetMessageHandlerMock();
var mockFileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ #"c:\Test\", new MockDirectoryData() },
{ #"c:\Test\subfolder1\myNewFile.txt", new MockFileData(string.Empty) }
});
var httpClient = new HttpClient(handlerMock.Object);
var sut = new Downloader(httpClient, mockFileSystem);
await sut.DownloadConfigFileAsync(BasePath, "http://fakeurl.com?path=%2Fconfiguration%2Flocal%2FTestFile.txt", _fixture.Create<string>());
handlerMock.Protected().Verify(
"SendAsync",
Times.Exactly(1),
ItExpr.Is<HttpRequestMessage>(req => req.Method == HttpMethod.Get),
ItExpr.IsAny<CancellationToken>());
mockFileSystem.File.Exists(FilePath).Should().BeTrue();
// Add assertion that the File.Delete has been called
}
The test freamwork has extensive unit tests itself.
Looking into ...tests\TestableIO.System.IO.Abstractions.TestingHelpers.Tests\MockFileDeleteTests.cs, it just counts the files, which I don't find overly satisying. If there would be a direct way, the creator would have used it.
var fileCount1 = fileSystem.Directory.GetFiles(directory, "*").Length;
fileSystem.File.Delete(path);
var fileCount2 = fileSystem.Directory.GetFiles(directory, "*").Length;
Assert.AreEqual(1, fileCount1, "File should have existed");
Assert.AreEqual(0, fileCount2, "File should have been deleted");
I am trying to test the AddCategory of the following CategoryService.
My problem is that I am having a hard time understanding what to mock/fake.
My attempt at the test is at the bottom.
I am using MOQ, xUnit and FluentAssertions.
I am using FluentValidation for the validators.
Category Service
public class CategoryService : ValidatingServiceBase, ICategoryService
{
private readonly IUnitOfWork unitOfWork;
private readonly IRepository<Category> categoryRepository;
private readonly IRepository<SubCategory> subCategoryRepository;
private readonly IValidationService validationService;
public CategoryService(
IUnitOfWork unitOfWork,
IRepository<Category> categoryRepository,
IRepository<SubCategory> subCategoryRepository,
IValidationService validationService)
: base(validationService)
{
this.unitOfWork = unitOfWork;
this.categoryRepository = categoryRepository;
this.subCategoryRepository = subCategoryRepository;
this.validationService = validationService;
}
public bool AddCategory(Category category)
{
var validationResult = validationService.Validate(category);
if (!validationResult.IsValid)
{
return false;
}
else
{
categoryRepository.Add(category);
return true;
}
}
public bool DoesCategoryExist(string categoryName)
{
return categoryRepository.Query().SingleOrDefault(x => x.Name == categoryName) != null;
}
}
Validation Service
public class ValidationService : ServiceBase, IValidationService
{
private readonly IValidatorFactory validatorFactory;
public ValidationService(IValidatorFactory validatorFactory)
{
Enforce.ArgumentNotNull(validatorFactory, "validatorFactory");
this.validatorFactory = validatorFactory;
}
public ValidationResult Validate<TEntity>(TEntity entity) where TEntity : class
{
var validator = validatorFactory.GetValidator<TEntity>();
return validator.Validate(entity);
}
}
Validator Factory
public class ValidatorFactory : IValidatorFactory
{
public IValidator GetValidator(Type type)
{
Enforce.ArgumentNotNull(type, "type");
return DependencyResolver.Current.GetService(typeof(IValidator<>).MakeGenericType(type)) as IValidator;
}
public IValidator<T> GetValidator<T>()
{
return DependencyResolver.Current.GetService<IValidator<T>>();
}
}
Category Validator
public class CategoryValidator : AbstractValidator<Category>
{
public CategoryValidator(ICategoryService service)
{
RuleFor(x => x.Name)
.NotEmpty()
.Must((category, name) =>
{
return service.DoesCategoryExist(name);
});
}
}
Unit Test Attempt
[Fact]
public void AddCategory_Should_ReturnTrue()
{
var category = new Category() { Name = "Cat1" };
var unitOfWork = new Mock<IUnitOfWork>();
var categoryRepo = new Mock<IRepository<Category>>();
var subCategoryRepo = new Mock<IRepository<SubCategory>>();
var mockCategoryService = new Mock<ICategoryService>();
var categoryValidator = new CategoryValidator(mockCategoryService.Object);
var validatorFactory = new Mock<IValidatorFactory>();
validatorFactory.Setup(x => x.GetValidator<CategoryValidator>()).Returns(categoryValidator as IValidator<CategoryValidator>);
var validationService = new ValidationService(validatorFactory.Object);
var categoryService = new CategoryService(
unitOfWork.Object,
categoryRepo.Object,
subCategoryRepo.Object,
validationService);
categoryService.AddCategory(category);
}
Well for the AddCategory method, I think you really only need two mocks, one for the ValidationService, and one for the CategoryRepository, because the other dependencies aren't exercised in that function and therefore are irrelevant
(the story might be different of course if your ctor throws on null arguments but in this case I think you are OK - albeit you might consider adding these checks in the future :)
Anyway, being pedantic, I'd nearly be inclined to write two (or more - maybe one for null input to verify it throws or returns false or whatever) "unit" tests for this function;
One to verify that given an invalid category, the function returns false,
One to verify that given a valid category, the function calls Add on the CategoryRepository dependency.
So it would look like this (sorry, this is using MSTest syntax as I'm not familiar with xUnit but it's the same idea). Also have not tested below for typos, etc :)
public void AddCategory_InvalidCategory_ShouldReturnFalse()
{
//Arrange
var mockValidator = new Mock<IValidator>();
//no matter what we pass to the validator, it will return false
mockValidator.Setup(v=>v.Validate(It.IsAny<Category>()).Returns(false);
var sut= new CategoryService(null,null,null,mockValidator.Object);
bool expected = false;
//ACT
bool actual = sut.AddCategory(new Category());
//ASSERT
Assert.AreEqual(expected,actual,"Validator didn't return false as expected");
}
public void AddCategory_ValidCategory_ShouldCallRepositoryAdd()
{
//Arrange
var mockValidator = new Mock<IValidator>();
//no matter what we pass to the validator, it will return true
mockValidator.Setup(v=>v.Validate(It.IsAny<Category>()).Returns(true);
var mockRepo = new Mock<IRepository<SubCategory>>();
mockRepo.Setup(r=>r.Add(It.IsAny<Category>())); //do not know or care what happens as this is a void method.
var sut= new CategoryService(null,mockRepo.Object,null,mockValidator.Object);
bool expected = false;
//ACT
bool actual = sut.AddCategory(new Category());
//ASSERT
mockRepo.Verify(r=>r.Add(It.IsAny<Category>(),Times.Exactly(1),"Repo ADD method not called or called too many times, etc");
Assert.AreEqual(expected,actual,"Add was called BUT the AddCategoryMethod didn't return true as expected"); //and of course you could be totally pedantic and create a new test method for that last assert ;)
}
The reason I favour this approach is because it forces you to consider the behaviour of the method under test, as well as ensuring that you don't involve any dependencies that are not being tested plus it means your test methods only create exactly what they need to in order to run the tests (and of course you can create some setup/teardown helpers to pre-create those mocks for you);
Of course you could put all the above into a single method but for the sake of saving a few LOC I hope you'll agree that having two separate tests to verify two separate behaviours is a more robust approach.
Just my 2c. hope it helps!
I am trying to write a unit test for actionfilter. i wrote some code but i didn't know if it is true or not. my action result code is below:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
HttpContext.Current.Response.Redirect("/kullanicigiris");
}
}
i add this actionresult top fo some controllers.
[AuthenticationFilter]
public class HomeController : Controller
i wrote a test code like this:
[TestMethod]
public void TestActionFilter()
{
const string expectedViewName = "Create";
const string username = "deneme";
// MockRepository mock=new MockRepository();
AccountController v=new AccountController();
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
context.SetupGet(p => p.User.Identity.Name).Returns(username);
context.SetupGet(p => p.Request.IsAuthenticated).Returns(false);
context.VerifyAll();
}
}
i wrote this for success. i will also write one more for failed. Is it a true approach?
Below is a class (Class1) that I want to test, but I'm not fully satisfied with my Unit Test. Please see below code samples.
System Under Test
public interface IRepository {
string GetParameter(int id);
}
public class Repository {
public string GetParameter(int id) {
return "foo";
}
}
public class ErrorInfo {
public string ErrorCodes { get; set; }
}
public interface IErrorProvider {
ErrorInfo BuildErrorMessage(string errorCodes);
}
public class ErrorProvider {
public ErrorInfo BuildErrorMessage(string errorCodes) {
return new ErrorInfo(){ErrorCodes = errorCodes};
}
}
public class Class1 {
private readonly IRepository _repository;
private readonly IErrorProvider _errorProvider;
public Class1(IRepository repository, IErrorProvider errorProvider) {
_repository = repository;
_errorProvider = errorProvider;
}
public List<ErrorInfo> GetErrorList(int id) {
var errorList = new List<ErrorInfo>();
string paramName = _repository.GetParameter(id);
if (string.IsNullOrEmpty(paramName)) {
string errorCodes = string.Format("{0}, {1}", 200, 201);
var error = _errorProvider.BuildErrorMessage(errorCodes);
errorList.Add(error);
}
return errorList;
}
}
Unit Tests
Below test passes and we check whether the correct error codes being used within the system under test.
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes2() {
//Arrange
var stubRepo = new Mock<IRepository>();
stubRepo.Setup(x => x.GetParameter(It.IsAny<int>())).Returns(string.Empty);
var stubErrorMock = new Mock<IErrorProvider>();
const int id = 5;
var sut = new Class1(stubRepo.Object, stubErrorMock.Object);
//Act
var result = sut.GetErrorList(id);
//Verify
string verifiableErrorCodes = "200, 201";
stubErrorMock.Verify(x => x.BuildErrorMessage(verifiableErrorCodes));
}
However I would prefer testing the end result. For example, I want to Assert against the error codes that have been used in the production code. Below test fails but I like to know your thoughts on how to Assert against the errorCodes that has been used in the system under test.
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes1() {
//Arrange
var stubRepo = new Mock<IRepository>();
stubRepo.Setup(x => x.GetParameter(It.IsAny<int>())).Returns(string.Empty);
string expectedErrorCodes = "200, 201";
var stubErrorRepo = new Mock<IErrorProvider>();
stubErrorRepo.Setup(e => e.BuildErrorMessage(It.IsAny<string>()));
const int id = 5;
var sut = new Class1(stubRepo.Object, stubErrorRepo.Object);
//Act
var result = sut.GetErrorList(id);
//Assert
Assert.AreEqual(expectedErrorCodes, result.Single().ErrorCodes);
}
What would be the correct way to test this error codes that has been used in the system?
I suggest to mock only the IRepository and use a real IErrorProvider. Then you can call GetErrorList(id) and check the result.
There is not really right or wrong answer and we have decided to use the Assert test as it test the end result.
I took the TDD approach and re-implemented/analysed as below.
Start with a failing test (to simplify the code I removed the Repository from both test and the sut)
//AssertTest
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes1()
{
//Arrange
const string expectedErrorCodes = "200, 201";
var stubErrorRepo = new Mock<IErrorProvider>();
stubErrorRepo.Setup(e => e.BuildErrorMessage(expectedErrorCodes)).Returns(new ErrorInfo() { ErrorCodes = expectedErrorCodes });
var sut = new Class1(stubErrorRepo.Object);
//Act
var result = sut.GetErrorList();
//Assert
Assert.AreEqual(expectedErrorCodes, result.Single().ErrorCodes);
}
//SUT
public IEnumerable<ErrorInfo> GetErrorList(int id)
{
yield return new ErrorInfo();
}
As you would expect the test fail.
Now if write enough production code to make this test pass.
public IEnumerable<ErrorInfo> GetErrorList()
{
yield return _errorProvider.BuildErrorMessage("200, 201");
}
The VerifyTest would still fail for the above SUT.
//VerifyTest
[TestMethod]
public void GetErrorList_WhenParameterIsEmpty_ReturnsExpectedErrorCodes2()
{
//Arrange
var stubErrorMock = new Mock<IErrorProvider>();
var sut = new Class1(stubErrorMock.Object);
//Act
sut.GetErrorList();
//Verify
string verifiableErrorCodes = "200, 201";
stubErrorMock.Verify(x => x.BuildErrorMessage(verifiableErrorCodes));
}
However if I want this test to pass, I can write the below production code as below
public IEnumerable<ErrorInfo> GetErrorList()
{
_errorProvider.BuildErrorMessage("200, 201");
return null;
}
Now the VerifyTest passes, but the AssertTest fails.
Both tests are valid in their own ways. However they test different semantics.
AssertTest test whether the end result contains the correct error codes. Verify test ensures
the method is called with the correct error codes. It is important to note that
the end value of the Assert test is based on the setup method "match" provided by the Moq
framework. In other words the setup dictates what the end result would be.
AssertTest would fail if the setup is configured incorrectly or the production code uses error codes that does not match the setup configuration.
It is preferred to use the AssertTest as it test the end result.
In a custom ActionFilter, I want check the attributes on the controller action that will be executed. Running through a small test application, the following works when launching the app in the asp.net development server-
public class CustomActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var someAttribute = filterContext.ActionDescriptor
.GetCustomAttributes(typeof(SomeAttribute), false)
.Cast<SomeAttribute>()
.SingleOrDefault();
if (someAttribute == null)
{
throw new ArgumentException();
}
// do something here
}
public override void OnActionExecuted(ActionExecutingContext filterContext)
{
// ...
}
}
An action method without SomeAttribute throws an ArgumentException and conversely, an action method with SomeAttribute does not. So far so good.
Now I would like to set up some unit tests for the ActionFilter, but how can I set up the action method upon which the OnActionExecuting method should run in the unit test? Using the following code doesn't find SomeAttribute on the action method which will be executed. Is the test set up correctly? Have I not arranged something correctly in the test? To clarify, the test is not complete but I'm not sure what I've missed such that someAttribute in OnActionExecuting in the test is null
[TestMethod]
public void Controller_With_SomeAttribute()
{
FakeController fakeController =
new FakeController();
ControllerContext controllerContext =
new ControllerContext(new Mock<HttpContextBase>().Object,
new RouteData(),
fakeController);
var actionDescriptor = new Mock<ActionDescriptor>();
actionDescriptor.SetupGet(x => x.ActionName).Returns("Action_With_SomeAttribute");
ActionExecutingContext actionExecutingContext =
new ActionExecutingContext(controllerContext,
actionDescriptor.Object,
new RouteValueDictionary());
CustomActionFilterAttribute customActionFilterAttribute = new CustomActionFilterAttribute ();
customActionFilterAttribute.OnActionExecuting(actionExecutingContext);
}
private class FakeController : Controller
{
[SomeAttribute]
ActionResult Action_With_SomeAttribute()
{
return View();
}
}
Since the ActionDescriptor property of ActionExecutingContext is virtual, you can just override that and provide your own implementation of ActionDescriptor.
Here are two tests that verify the two branches through the current implementation of OnActionExecuting:
[ExpectedException(typeof(ArgumentException))]
[TestMethod]
public void OnActionExecutingWillThrowWhenSomeAttributeIsNotPresent()
{
// Fixture setup
var ctxStub = new Mock<ActionExecutingContext>();
ctxStub.Setup(ctx => ctx.ActionDescriptor.GetCustomAttributes(typeof(SomeAttribute), false))
.Returns(new object[0]);
var sut = new CustomActionFilterAttribute();
// Exercise system
sut.OnActionExecuting(ctxStub.Object);
// Verify outcome (expected exception)
// Teardown
}
[TestMethod]
public void OnActionExecutingWillNotThrowWhenSomeAttributeIsPresent()
{
// Fixture setup
var ctxStub = new Mock<ActionExecutingContext>();
ctxStub.Setup(ctx => ctx.ActionDescriptor.GetCustomAttributes(typeof(SomeAttribute), false))
.Returns(new object[] { new SomeAttribute() });
var sut = new CustomActionFilterAttribute();
// Exercise system
sut.OnActionExecuting(ctxStub.Object);
// Verify outcome (no exception indicates success)
// Teardown
}