Setup and verify expression with Moq - c#

Is there a way to setup and verify a method call that use an Expression with Moq?
The first attempt is the one I would like to get it to work, while the second one is a "patch" to let the Assert part works (with the verify part still failing)
string goodUrl = "good-product-url";
[Setup]
public void SetUp()
{
productsQuery.Setup(x => x.GetByFilter(m=>m.Url== goodUrl).Returns(new Product() { Title = "Good product", ... });
}
[Test]
public void MyTest()
{
var controller = GetController();
var result = ((ViewResult)controller.Detail(goodUrl)).Model as ProductViewModel;
Assert.AreEqual("Good product", result.Title);
productsQuery.Verify(x => x.GetByFilter(t => t.Url == goodUrl), Times.Once());
}
Thet test fail at the Assert and throw a null reference exception, because the method GetByFilter is never called.
If instead I use this
[Setup]
public void SetUp()
{
productsQuery.Setup(x => x.GetByFilter(It.IsAny<Expression<Func<Product, bool>>>())).Returns(new Product() { Title = "Good product", ... });
}
The test pass the Assert part, but this time is the Verify that fail saying that it is never called.
Is there a way to setup a method call with a specific expression instead of using a generic It.IsAny<>()?
Update
I tried also the suggestion by Ufuk Hacıoğulları in the comments and created the following
Expression<Func<Product, bool>> goodUrlExpression = x => x.UrlRewrite == "GoodUrl";
[Setup]
public void SetUp()
{
productsQuery.Setup(x => x.GetByFilter(goodUrlExpression)).Returns(new Product() { Title = "Good product", ... });
}
[Test]
public void MyTest()
{
...
productsQuery.Verify(x => x.GetByFilter(goodUrlExpression), Times.Once());
}
But I get a null reference exception, as in the first attempt.
The code in my controller is as follow
public ActionResult Detail(string urlRewrite)
{
//Here, during tests, I get the null reference exception
var entity = productQueries.GetByFilter(x => x.UrlRewrite == urlRewrite);
var model = new ProductDetailViewModel() { UrlRewrite = entity.UrlRewrite, Culture = entity.Culture, Title = entity.Title };
return View(model);
}

The following code demonstrates how to test in such scenarios. The general idea is that you execute the passed in query against a "real" data. That way, you don't even need "Verify", as if the query is not right, it will not find the data.
Modify to suit your needs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Moq;
using NUnit.Framework;
namespace StackOverflowExample.Moq
{
public class Product
{
public string UrlRewrite { get; set; }
public string Title { get; set; }
}
public interface IProductQuery
{
Product GetByFilter(Expression<Func<Product, bool>> filter);
}
public class Controller
{
private readonly IProductQuery _queryProvider;
public Controller(IProductQuery queryProvider)
{
_queryProvider = queryProvider;
}
public Product GetProductByUrl(string urlRewrite)
{
return _queryProvider.GetByFilter(x => x.UrlRewrite == urlRewrite);
}
}
[TestFixture]
public class ExpressionMatching
{
[Test]
public void MatchTest()
{
//arrange
const string GOODURL = "goodurl";
var goodProduct = new Product {UrlRewrite = GOODURL};
var products = new List<Product>
{
goodProduct
};
var qp = new Mock<IProductQuery>();
qp.Setup(q => q.GetByFilter(It.IsAny<Expression<Func<Product, bool>>>()))
.Returns<Expression<Func<Product, bool>>>(q =>
{
var query = q.Compile();
return products.First(query);
});
var testController = new Controller(qp.Object);
//act
var foundProduct = testController.GetProductByUrl(GOODURL);
//assert
Assert.AreSame(foundProduct, goodProduct);
}
}
}

Related

XUnit test for the response body content

I am really new to XUnit and I will appreciate some help.
Controller
I have a really simple API method that adds a bug comment
[HttpPost("{bugId}/comment")]
public async Task<IActionResult> AddComment(Guid bugId, [FromBody] AddCommentForm form)
{
return await _bugService.AddComment(bugId, form) switch
{
Option<BugViewModel>.Some(var bug) => Ok(bug),
Option<BugViewModel>.None => NotFound(),
_ => throw new InvalidOperationException()
};
}
Service
The BugService method AddComment looks like this
public async Task<Option<BugViewModel>> AddComment(Guid bugId, AddCommentForm form)
{
if (await DbBugs.SingleOrDefaultAsync(x => x.Id == bugId) is { } bug)
{
var bugComment = new BugComment
{
Text = form.Text,
Commenter = form.Commenter,
CommentedAt = DateTime.Now,
Bug = bug
};
await _dbContext.BugComments.AddAsync(bugComment);
await _dbContext.SaveChangesAsync();
return new Option<BugViewModel>.Some(BugViewModel.FromData(bug));
}
return new Option<BugViewModel>.None();
}
ViewModels
I am adding the implementation of BugViewModel and BugCommentViewModel with their static FromData methods
public class BugViewModel
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public List<BugCommentViewModel> Comments { get; set; }
public static BugViewModel FromData(Bug bug)
{
return new BugViewModel
{
Id = bug.Id,
Title = bug.Title,
Description = bug.Description,
Comments = bug.Comments.Select(BugCommentViewModel.FromData).ToList()
};
}
}
public class BugCommentViewModel
{
public Guid Id { get; set; }
public string Text { get; set; }
public string Commenter { get; set; }
public DateTime CommentedAt { get; set; }
public static BugCommentViewModel FromData(BugComment comment)
{
return new BugCommentViewModel
{
Id = comment.Id,
Text = comment.Text,
Commenter = comment.Commenter,
CommentedAt = comment.CommentedAt.ToLocalTime()
};
}
}
Testing
The Unit Tests look like this
public class BugContollerTests
{
private class Fixture
{
public IBugService BugService { get; } = Substitute.For<IBugService>();
public BugController GetSut() => new BugController(BugService);
}
private readonly Fixture _fixture = new Fixture();
[Fact]
public async Task Create_ResponseBodyIsCreatedBug()
{
var bug = BugViewModel.FromData(FakeBug.I.Generate());
_fixture.BugService.Create(Arg.Any<CreateBugForm>()).Returns(bug);
var sut = _fixture.GetSut();
var response = Assert.IsAssignableFrom<CreatedAtActionResult>(await sut.Create(new CreateBugForm()));
Assert.Same(bug, response.Value);
}
[Fact]
public async Task AddComment_CommentIsAddedtoViewModel()
{
_fixture.BugService.AddComment(Arg.Any<Guid>(), Arg.Any<AddCommentForm>()).Returns(new Option<BugViewModel>.Some(new BugViewModel()));
var sut = _fixture.GetSut();
var response = Assert.IsAssignableFrom<ObjectResult>(await sut.AddComment(Guid.Empty,new AddCommentForm()));
Assert.Single(((BugViewModel) response.Value).Comments);
}
}
So, the Test method I had as an example was Create_ResponseBodyIsCreatedBug but the question I have is regarding the second test method that I have created AddComment_CommentIsAddedtoViewModel().
What I am trying to do is:
you see that the BugService.AddComment -> it adds the comment with the Bug Guid we have provided and basically we return BugViewModel with that Comment added to the Comments collection.
test: that WHEN I add a BugComment it is returned in the ViewModel response and we have added exactly one Comment to the bug.
this line
var response = Assert.IsAssignableFrom<ObjectResult>(await sut.AddComment(Guid.Empty,new AddCommentForm()));
the response.Value is a BugViewModel with empty properties and the Comment property is empty without my inserted comment.
And on this line I get an exception as
Assert.Single(((BugViewModel) response.Value).Comments);
as the Comments property is null.
Look, at this line
_fixture.BugService.AddComment(Arg.Any<Guid>(), Arg.Any<AddCommentForm>())
.Returns(
new Option<BugViewModel>.Some(new BugViewModel()));
You setup your fake BugService to return an empty BugViewModel, which indeed would have Comments equal to null because you initialize it nowhere except FromData.
Use same approach you did in a first test
_fixture.BugService.AddComment(Arg.Any<Guid>(), Arg.Any<AddCommentForm>())
.Returns(
new Option<BugViewModel>.Some(
BugViewModel.FromData(FakeBug.I.Generate())));
Or introduce a constructor
public BugViewModel(Guid id, string title, string description, List<BugCommentViewModel> comments)
{
Id = id;
Title = title;
Description = description;
Comments = comments;
}
// Comments are not NULL now
public BugViewModel(): this(Guid.Empty, string.Empty, string.Empty, new List<BugCommentViewModel>())
{
}
In addition, I don't see any purpose of unit testing a mocked dependency of BugController .
Assert.Single(((BugViewModel) response.Value).Comments);
Better move this logic to a separate BugServiceTest which would validate the number of comments.
One more suggestion in regards to unit testing is instead of relying on ObjectResult, write better three tests:
[Fact]
public async Task AddComment_CommentIsAddedtoViewModel_Success()
{
_fixture.BugService.AddComment(Arg.Any<Guid>(), Arg.Any<AddCommentForm>())
.Returns(
new Option<BugViewModel>.Some(
BugViewModel.FromData(FakeBug.I.Generate())));
var sut = _fixture.GetSut();
Assert.IsAssignableFrom<OkResult>(
await sut.AddComment(Guid.Empty,new AddCommentForm()));
}
[Fact]
public async Task AddComment_BugNotFound()
{
_fixture.BugService.AddComment(Arg.Any<Guid>(), Arg.Any<AddCommentForm>())
.Returns(Option<BugViewModel>.None);
var sut = _fixture.GetSut();
Assert.IsAssignableFrom<NotFoundResult>(
await sut.AddComment(Guid.Empty,new AddCommentForm()));
}
public async Task AddComment_ThrowsForNonsenseData()
{
// Idk Option is value or reference type, so I use default(T)
_fixture.BugService.AddComment(Arg.Any<Guid>(), Arg.Any<AddCommentForm>())
.Returns(default(Option<BugViewModel>));
var sut = _fixture.GetSut();
await Assert.ThrowsAsync<InvalidOperationException>(
() => sut.AddComment(Guid.Empty, new AddCommentForm()));
}
Tell me if that helps
The problem is that you are mocking BugService.
You set mock to AddComment method and setup to return HARD CODED value.
That's why this your code is not called any more.
if (await DbBugs.SingleOrDefaultAsync(x => x.Id == bugId) is { } bug)
{
var bugComment = new BugComment
{
Text = form.Text,
Commenter = form.Commenter,
CommentedAt = DateTime.Now,
Bug = bug
};
await _dbContext.BugComments.AddAsync(bugComment);
await _dbContext.SaveChangesAsync();
return new Option<BugViewModel>.Some(BugViewModel.FromData(bug));
}
Your tests is written to check ONLY Controller.
if you want to check BugService too, you should NOT setup mocks for BugService and setup mocks to this:
DbBugs.SingleOrDefaultAsync(x => x.Id == bugId)
//and this
_dbContext.BugComments.AddAsync(bugComment);
//and this
_dbContext.SaveChangesAsync();

how to mock.SingleOrDefault() with Moq and C#

I've seen a few questions like this floating around but I'm looking for a good explination of how to get around this. I understand that Moq can't mock the extension call, but I'm just looking for a really good example. In the current code I there is a call like
var thing = listOfthings.myList.SingleOrDefault(lt => lt.Name== "NameToFind");
I've tried
MockedlistOfThings.Setup(x => x.myList.SingleOrDefault(o => o.Name == "NameToFind")).Returns(fakeObject);
Just looking for a good work around. thanks.
To further elaborate on how this situation came up, we are currently running a translation engine against large sets of data, that has to be run line by line. This translation engine passes in an Interface called IListOfthings. listOfthings is actually holding reference data in a dictionary that is preloaded in another call higher up in the program. I have created a "fakeObject" <- dictionary that holds my fake data that the method can use. I have Mocked the IlistOfthings which is passed in to the calling method. but I don't see how to fake the SingleOrDefault call.
Simplifed method below.
Public class ClassIMTesting
{
public void Translate(myObject obj, IlistOfThings listOfthings){
var thing = listOfthings.MyList.SingleOrDefault(lt => lt.Name== "NameToFind");
//Other logic here .....
}
}
public class Thing()
{
public string Name { get; set; }
public Dictionary MyDict { get; set; }
}
[TestFixture()]
public class MyCodeTest
{
MyObject myObj;
Mock<IListOfthings> listOfThings;
Thing thing;
[SetUp]
public void Setup()
{
myObj = new MyObject();
_thing = new thing();
_thing.Name = "MyName";
var myDict = new Dictionary<string, string>();
myDict.Add("70,~", "");
myDict.Add("70,145", "expectedResult");
myDict.Add("911,", "expectedResult");
thing.MyDict = myDict;
listOfThings = new Mock<IListOfthings>();
listOfThings.Setup(x => x.MyList.SingleOrDefault(o => o.Name == "MyName")).Returns(thing);
}
[TestCase("70", "~", "70070")]
[TestCase("70", "145", "expectedResult")]
[TestCase("911", "", "expectedResult")]
public void TranslateTest(string iTC, string ITCode, string expectedResult)
{
myObject.ITC = iTC;
myObject.ITCode = iTCode;
ClassIMTesting p = new ClassIMTesting();
p.Translate(myObject, listofThings.Object);
Assert.That(myObject.ITC3Code, Is.EqualTo(expectedResult));
}
}
public interface IListOfThings
{
List<Thing> MyList{ get; set; }
}
Given
public interface IListOfThings {
List<Thing> MyList { get; set; }
}
public class Thing() {
public string Name { get; set; }
public Dictionary MyDict { get; set; }
}
In order to provide a mock to satisfy the following example
public class ClassImTesting {
public Thing Translate(IlistOfThings listOfthings){
var thing = listOfthings.MyList.SingleOrDefault(lt => lt.Name== "NameToFind");
return thing
}
}
The mock just needs to return a collection that will allow the SingleOrDefault extension to behave as expected when invoked.
For example
//Arrrange
Mock<IListOfthings> listOfThings = new Mock<IListOfthings>();
var thing = new Thing {
Name = "NameToFind",
//...
};
List<Thing> list = new List<Thing>() { thing };
listOfThings.Setup(_ => _.MyList).Returns(list);
var subject = new ClassImTesting();
//Act
var actual = subject.Translate(listOfThings.Object);
//Assert
Assert.That(actual, Is.EqualTo(thing));
By having the mock return an actual List<Thing>, when
var thing = listOfthings.MyList.SingleOrDefault(lt => lt.Name== "NameToFind");
is invoked, the SingleOrDefault extension acts on a list where I can behave as expected.

Set a Mock Object Property Then Verify It Is Used in Method Call

I'm attempting to create a test which verifies that a specific method is called. The method accepts two parameters, and I'd like to check that it gets called with that object having a specific property set.
Here's the code:
private void InitialiseContentTypes()
{
IContentType blogContentTypeComposition = _blogContentTypeFactory.GetComposition();
_umbracoContentTypeService.Save(blogContentTypeComposition);
}
This gets the composition from a factory, then uses it in the Save method. In the test, the blogContentTypeComposition should have a property called alias set to aldusBlogComposition (blogContentTypeComposition.Alias).
Here's the test code:
[Test]
[TestCase("aldusBlogComposition")]
public void Initialise_WhenCalled_SavesComposition(string alias)
{
Mock<IContentType> contentType = new Mock<IContentType>();
_blogContentTypeFactory
.Setup(f => f.GetComposition())
.Callback(() => { contentType.SetupProperty(ct => ct.Alias, alias); });
_component.Initialize();
_contentTypeService.Verify(s => s.Save(It.Is<IContentType>(ct => ct.Alias == alias), It.IsAny<int>()), Times.Once);
}
This code creates a mock IContentType and when GetComposition is called, it sets the alias to aldusBlogComposition. Then the Verify should check that the Save method runs once, with the first parameter an IContentType with the alias property set to aldusBlogComposition.
When I run the test, this throws an error (below) which I suspect means that the mock isn't being used in the Verify method call.
Object reference not set to an instance of an object.
What am I missing?
EDIT:
The error is being thrown as part of the contentTypeService.Verify(s => s.Save(It.Is<IContentType>(ct => ct.Alias == alias), It.IsAny<int>()), Times.Once); call. The only thing I can see being null is ct - if I swap this out for just It.IsAny<IContentType>() the error isn't thrown. I understand what a null reference is, but I don't understand why the parameter is null.
Full classes for reference:
Tests class:
using Moq;
using NUnit.Framework;
using Papermoon.Umbraco.Aldus.Core.Components;
using Papermoon.Umbraco.Aldus.Core.Factories.ContentTypes.Interfaces;
using Papermoon.Umbraco.Aldus.Core.Services.Interfaces;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Tests.Components
{
[TestFixture]
public class ContentTypeComponentTests
{
private Mock<IContentTypeService> _contentTypeService;
private Mock<IAldusContentTypeContainerService> _contentTypeContainerService;
private Mock<IBlogContentTypeFactory> _blogContentTypeFactory;
private ContentTypeComponent _component;
[SetUp]
public void SetUp()
{
_contentTypeService = new Mock<IContentTypeService>();
_contentTypeContainerService = new Mock<IAldusContentTypeContainerService>();
_blogContentTypeFactory = new Mock<IBlogContentTypeFactory>();
_component = new ContentTypeComponent(_contentTypeService.Object, _contentTypeContainerService.Object, _blogContentTypeFactory.Object);
}
[Test]
public void Initialize_WhenCalled_GetAldusContainer()
{
_component.Initialize();
_contentTypeContainerService.Verify(s => s.GetContainer("Aldus", 1, -1));
}
[Test]
public void Initialise_AldusContainerExists_GetAldusCompositionContainer()
{
_contentTypeContainerService
.Setup(s => s.GetContainer("Aldus", 1, -1))
.Returns(new EntityContainer(Constants.ObjectTypes.DocumentType)
{
Id = 1
});
_component.Initialize();
_contentTypeContainerService.Verify(s => s.GetContainer("Aldus Compositions", 2, 1));
}
[Test]
public void Initialise_AldusContainerDoesNotExist_DoNoGetAldusCompositionsContainer()
{
_contentTypeContainerService
.Setup(s => s.GetContainer("Aldus", 1, -1))
.Returns((EntityContainer) null);
_component.Initialize();
_contentTypeContainerService.Verify(s => s.GetContainer("Aldus Compositions", 2, It.IsAny<int>()), Times.Never());
}
[Test]
[TestCase("aldusBlogComposition")]
public void Initialise_WhenCalled_SavesComposition(string alias)
{
Mock<IContentType> contentType = new Mock<IContentType>();
_blogContentTypeFactory
.Setup(f => f.GetComposition())
.Callback(() => { contentType.SetupProperty(ct => ct.Alias, alias); });
_component.Initialize();
_contentTypeService.Verify(s => s.Save(It.IsAny<IContentType>(), It.IsAny<int>()), Times.Once);
}
[Test]
public void Initialise_WhenCalled_SavesBlogContentType()
{
Mock<IContentType> contentType = new Mock<IContentType>();
contentType.SetupProperty(ct => ct.Alias, "aldus");
_blogContentTypeFactory
.Setup(f => f.GetContentType())
.Returns(contentType.Object);
_component.Initialize();
_contentTypeService.Verify(s => s.Save(contentType.Object, It.IsAny<int>()), Times.Once);
}
}
}
Component class:
using Papermoon.Umbraco.Aldus.Core.Factories.ContentTypes.Interfaces;
using Papermoon.Umbraco.Aldus.Core.Services.Interfaces;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Components
{
public class ContentTypeComponent : IComponent
{
private readonly IAldusContentTypeContainerService _contentTypeContainerService;
private readonly IContentTypeService _umbracoContentTypeService;
private EntityContainer _aldusContainer;
private readonly IBlogContentTypeFactory _blogContentTypeFactory;
public ContentTypeComponent(
IContentTypeService umbracoContentTypeService,
IAldusContentTypeContainerService contentTypeContainerService,
IBlogContentTypeFactory blogContentTypeFactory)
{
_umbracoContentTypeService = umbracoContentTypeService;
_contentTypeContainerService = contentTypeContainerService;
_blogContentTypeFactory = blogContentTypeFactory;
}
public void Initialize()
{
InitialiseContainers();
InitialiseContentTypes();
}
private void InitialiseContainers()
{
_aldusContainer = _contentTypeContainerService.GetContainer("Aldus", 1);
if (_aldusContainer != null)
{
_contentTypeContainerService.GetContainer("Aldus Compositions", 2, _aldusContainer.Id);
}
}
private void InitialiseContentTypes()
{
IContentType blogContentTypeComposition = _blogContentTypeFactory.GetComposition();
_umbracoContentTypeService.Save(blogContentTypeComposition);
IContentType blogContentType = _blogContentTypeFactory.GetContentType();
_umbracoContentTypeService.Save(blogContentType);
}
public void Terminate() { }
}
}
And the blog factory class:
using System.Collections.Generic;
using System.Linq;
using Papermoon.Umbraco.Aldus.Core.Factories.ContentTypes.Interfaces;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Factories.ContentTypes
{
public class BlogContentTypeFactory : ContentTypeFactory, IBlogContentTypeFactory
{
public BlogContentTypeFactory(
IContentTypeService contentTypeService,
IPapermoonContentTypeService papermoonContentTypeService,
IPapermoonContentTypeContainerService papermoonContentTypeContainerService,
IPapermoonTemplateService papermoonTemplateService)
: base(
contentTypeService,
papermoonContentTypeService,
papermoonContentTypeContainerService,
papermoonTemplateService) { }
public IContentType GetComposition()
{
Composition = ContentTypeService.Get("aldusBlogComposition");
if (Composition == null)
{
Composition = new ContentType(AldusCompositionsContainer.Id);
}
Composition.Name = "Aldus Blog Composition";
Composition.Alias = "aldusBlogComposition";
Composition.Description = "A composition for the Aldus blog listing.";
Composition.Icon = "icon-settings";
return Composition;
}
public IContentType GetContentType()
{
ContentType = ContentTypeService.Get("aldusBlog");
if (ContentType == null)
{
ContentType = new ContentType(AldusContainer.Id);
}
ContentType.Name = "Blog";
ContentType.Alias = "aldusBlog";
ContentType.Description = "Aldus blog listing.";
ContentType.Icon = "icon-article";
ContentType.AllowedTemplates = PapermoonTemplateService.Get(new [] { "AldusBlog" });
ContentType.SetDefaultTemplate(ContentType.AllowedTemplates.First());
ContentType.ContentTypeComposition =
PapermoonContentTypeService.GetCompositions(ContentType, new List<string> {"aldusBlogComposition"});
return ContentType;
}
}
}
And finally, the content type factory class:
using System.Collections.Generic;
using System.Linq;
using Papermoon.Umbraco.Aldus.Core.Factories.ContentTypes.Interfaces;
using Papermoon.Umbraco.Utils.Services.Interfaces;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Papermoon.Umbraco.Aldus.Core.Factories.ContentTypes
{
public class BlogContentTypeFactory : ContentTypeFactory, IBlogContentTypeFactory
{
public BlogContentTypeFactory(
IContentTypeService contentTypeService,
IPapermoonContentTypeService papermoonContentTypeService,
IPapermoonContentTypeContainerService papermoonContentTypeContainerService,
IPapermoonTemplateService papermoonTemplateService)
: base(
contentTypeService,
papermoonContentTypeService,
papermoonContentTypeContainerService,
papermoonTemplateService) { }
public IContentType GetComposition()
{
Composition = ContentTypeService.Get("aldusBlogComposition");
if (Composition == null)
{
Composition = new ContentType(AldusCompositionsContainer.Id);
}
Composition.Name = "Aldus Blog Composition";
Composition.Alias = "aldusBlogComposition";
Composition.Description = "A composition for the Aldus blog listing.";
Composition.Icon = "icon-settings";
return Composition;
}
public IContentType GetContentType()
{
ContentType = ContentTypeService.Get("aldusBlog");
if (ContentType == null)
{
ContentType = new ContentType(AldusContainer.Id);
}
ContentType.Name = "Blog";
ContentType.Alias = "aldusBlog";
ContentType.Description = "Aldus blog listing.";
ContentType.Icon = "icon-article";
ContentType.AllowedTemplates = PapermoonTemplateService.Get(new [] { "AldusBlog" });
ContentType.SetDefaultTemplate(ContentType.AllowedTemplates.First());
ContentType.ContentTypeComposition =
PapermoonContentTypeService.GetCompositions(ContentType, new List<string> {"aldusBlogComposition"});
return ContentType;
}
}
}
Furthermore, I've tried adding a call to .Returns but still see the error. I've tried the following ways:
After the callback:
_blogContentTypeFactory
.Setup(f => f.GetComposition())
.Callback(() => { contentType.SetupProperty(ct => ct.Alias == alias); })
.Returns(contentType.Object);
Assignment as part of the return:
_blogContentTypeFactory
.Setup(f => f.GetComposition())
.Returns(contentType.SetupProperty(ct => ct.Alias, alias).Object);
Is it because you are missing the .Returns usage on the Mock factory instead?
contentType.SetupProperty(ct => ct.Alias, alias)
_blogContentTypeFactory
.Setup(f => f.GetComposition())
.Returns(contentType.SetupProperty);
Hard to tell without seeing more code around the instantiation of the concrete class.
There are a few ways to configure the mock and its property.
The following uses the LINQ to Mocks appraoch
[Test]
[TestCase("aldusBlogComposition")]
public void Initialise_WhenCalled_SavesComposition(string alias) {
//Arrange
IContentType contentType = Mock.Of<IContentType>(_ => _.ALias == alias);
_blogContentTypeFactory
.Setup(_ => _.GetComposition())
.Returns(contentType);
//Act
_component.Initialize();
//Assert
_contentTypeService.Verify(s => s.Save(It.Is<IContentType>(ct => ct.Alias == alias), It.IsAny<int>()), Times.Once);
}
You could have even verified that it was the same returned instance that was passed
//...omitted for brevity
//Assert
_contentTypeService.Verify(s => s.Save(contentType, It.IsAny<int>()), Times.Once);
//...
Turns out that Verify set up was right but a null value was being returned from the GetContentType method, I just need to set up a return:
_blogContentTypeFactory
.Setup(f => f.GetContentType())
.Returns(Mock.Of<IContentType>());

How to mock nested properties and objects and their functions?

I have the code below which I would like to test, but I'm not sure whether it is possible or not.
I have EF repositories and they are put together to a class as public properties. I don't know exactly whether it is bad solution or not, but it is easier to manage the code and its dependencies. Only the testability is still a question.
Purpose of my test is injecting data via
administrationRepository.ModuleScreen.GetAll()
method and catch the result. I know that it can be tested once it is deployed, but I want the tests in build time in order to have as fast feedback as possible.
I went through questions and answers here, but I cannot find answers. In my code I got to the point where the property is set up, but when I call the administrationRepoMock.Object.ModuleScreen.GetAll() ReSharper offers only the methods coming from Entitiy Framework and not the Moq related functions.
It is possible what I want? If so, how? Is my design suitable for this? If not can you give me articles, urls where I can see examples?
Repository:
public interface IModuleScreen
{
IEnumerable<DomainModel.Administration.ModuleScreen> GetAll();
}
public interface IAdministrationRepository
{
IModuleScreen ModuleScreen { get; }
}
public partial class AdministrationRepository : IAdministrationRepository
{
public virtual IModuleScreen ModuleScreen { get; private set; }
public AdministrationRepository( IModuleScreen moduleScreen )
{
this.ModuleScreen = moduleScreen;
}
}
Application:
public partial class DigitalLibraryApplication : IDigitalLibraryApplication
{
private IAdministrationRepository _administrationRepository;
private IMapper.IMapper.IMapper _mapper;
private IDiLibApplicationHelper _dilibApplicationHelper;
#region Ctor
public DigitalLibraryApplication( IAdministrationRepository administrationRepository, IMapper.IMapper.IMapper mapper, IDiLibApplicationHelper diLibApplicationHelper)
{
_administrationRepository = administrationRepository;
_mapper = mapper;
_dilibApplicationHelper = diLibApplicationHelper;
}
#endregion
public IEnumerable<ModuleScreenContract> GetModuleScreens()
{
//inject data here
IEnumerable<ModuleScreen> result = _administrationRepository.ModuleScreen.GetAll();
List<ModuleScreenContract> mappedResult = _mapper.MapModuleScreenToModuleScreenContracts(result);
return mappedResult;
}
}
Test code:
[Test]
public void ItCalls_ModuleRepository_Get_Method()
{
List<SayusiAndo.DiLib.DomainModel.Administration.ModuleScreen> queryResult = new List<SayusiAndo.DiLib.DomainModel.Administration.ModuleScreen>()
{
new DomainModel.Administration.ModuleScreen()
{
Id = 100,
},
};
var moduleScreenMock = new Mock<IModuleScreen>();
moduleScreenMock.Setup(c => c.GetAll()).Returns(queryResult);
administrationRepoMock.SetupProperty(c => c.ModuleScreen, moduleScreenMock.Object);
var mapperMock = new Mock<IMapper.IMapper.IMapper>();
var dilibApplicationHerlperMock = new Mock<IDiLibApplicationHelper>();
IDigitalLibraryApplication app = new DigitalLibraryApplication( administrationRepoMock.Object, mapperMock.Object, dilibApplicationHerlperMock.Object );
app.GetModules();
//issue is here
administrationRepoMock.Object.ModuleScreen.GetAll() //???
}
Here is a refactoring of your test that passes when run. You can update the pass criteria to suit you definition of a successful test.
[Test]
public void ItCalls_ModuleRepository_Get_Method() {
// Arrange
List<ModuleScreen> queryResult = new List<ModuleScreen>()
{
new ModuleScreen()
{
Id = 100,
},
};
//Building mapped result from query to compare results later
List<ModuleScreenContract> expectedMappedResult = queryResult
.Select(m => new ModuleScreenContract { Id = m.Id })
.ToList();
var moduleScreenMock = new Mock<IModuleScreen>();
moduleScreenMock
.Setup(c => c.GetAll())
.Returns(queryResult)
.Verifiable();
var administrationRepoMock = new Mock<IAdministrationRepository>();
administrationRepoMock
.Setup(c => c.ModuleScreen)
.Returns(moduleScreenMock.Object)
.Verifiable();
var mapperMock = new Mock<IMapper>();
mapperMock.Setup(c => c.MapModuleScreenToModuleScreenContracts(queryResult))
.Returns(expectedMappedResult)
.Verifiable();
//NOTE: Not seeing this guy doing anything. What's its purpose
var dilibApplicationHerlperMock = new Mock<IDiLibApplicationHelper>();
IDigitalLibraryApplication app = new DigitalLibraryApplication(administrationRepoMock.Object, mapperMock.Object, dilibApplicationHerlperMock.Object);
//Act (Call the method under test)
var actualMappedResult = app.GetModuleScreens();
//Assert
//Verify that configured methods were actually called. If not, test will fail.
moduleScreenMock.Verify();
mapperMock.Verify();
administrationRepoMock.Verify();
//there should actually be a result.
Assert.IsNotNull(actualMappedResult);
//with items
CollectionAssert.AllItemsAreNotNull(actualMappedResult.ToList());
//There lengths should be equal
Assert.AreEqual(queryResult.Count, actualMappedResult.Count());
//And there should be a mapped object with the same id (Assumption)
var expected = queryResult.First().Id;
var actual = actualMappedResult.First().Id;
Assert.AreEqual(expected, actual);
}

Setup for testing a Linq query on a LinqToExcel IExcelQueryFactory

Using c#, Moq, MSTest, LinqToExcel
I'm having trouble figuring out the best way to Setup() a mock for a response from a Linq query on a Linq-to-Excel IExcelQueryFactory.
I think I should expect the Linq Query to return something of type delegate, but I'm not quite sure what that should look like
Can anyone suggest what my Return() should look like in the Moq Setup() below?
Also, any toughts on my approach to testing and mocking these Lynq methods? Should I be approaching this differently?
Thanks! I'm going to go book up on delegates now. :)
The Test
[TestClass]
public class ThingsSheetTests
{
[TestMethod]
public void GetRows_ReturnsListOfThings()
{
// Arrange
var mockExcelQueryFactory = new Mock<IExcelQueryFactory>();
var thingsSheet = new ThingsSheet(mockExcelQueryFactory.Object, "file", "worksheet");
mockExcelQueryFactory
.Setup(x => x.Worksheet<Thing>(It.IsAny<string>))
// I think this is correctly casting to a delegate
// however ExelQuerable constructor needs arguments:
// public ExcelQueryable(IQueryProvider provider, Expression expression);
// looking into what kind of IQueryProvider and Expression I should supply.
.Returns(Action(() => new ExcelQueryable<Thing> { })); // getting closer!
// Act
thingsSheet.GetRows();
// Assert
mockExcelQueryFactory.Verify();
}
}
The Class and Method I'm testing
public class ThingsSheet
{
private string importFile;
private string worksheetName;
private IExcelQueryFactory excelQueryFactory;
public ThingsSheet(IExcelQueryFactory excelQueryFactory, string importFile, string worksheetName)
{
this.excelQueryFactory = excelQueryFactory;
this.importFile = importFile;
this.worksheetName = worksheetName;
this.AddMappings();
}
private void AddMappings()
{
excelQueryFactory.AddMapping<Thing>(t => t.Id, "Thing ID");
}
public List<Thing> GetRows()
{
excelQueryFactory.AddMapping<Thing>(t => t.Id, "Thing ID");
var things = from thing in excelQueryFactory.Worksheet<Thing>(this.worksheetName)
select new Thing { };
return things.ToList<Thing>();
}
}
You can use e.g. a method which returns your fake data.
mockExcelQueryFactory
.Setup(x => x.Worksheet<Thing>(It.IsAny<string>()))
.Returns(ExcelQueryableOfThing());
Lets say Thing class looks like this:
public class Thing
{
public string Id { get; set; }
public string Name { get; set; }
}
Then in the method ExcelQueryableOfThing() you have to mock the CreateQuery<TElement>(Expression expression) method of IQueryProvider provider. Something like this:
private ExcelQueryable<Thing> ExcelQueryableOfThing()
{
var things = new List<Thing>
{
new Thing
{
Id = "1",
Name = "Adam"
},
new Thing
{
Id = "1",
Name = "Eva"
}
}
.AsQueryable();
Mock<IQueryProvider> queryProvider = new Mock<IQueryProvider>();
queryProvider
.Setup(p => p.CreateQuery<Thing>(It.IsAny<Expression>()))
.Returns(() => things);
Expression expressionFake = Expression.Constant(new List<Thing>().AsQueryable());
return new ExcelQueryable<Thing>(queryProvider.Object, expressionFake);
}
Then in the unit test thingsSheet.GetRows() will return your fake data (Adam and Eva :). HTH
[TestMethod]
public void GetRows_ReturnsListOfThings()
{
// Arrange
Mock<IExcelQueryFactory> mockExcelFile = new Mock<IExcelQueryFactory>();
var thingsSheet = new ThingsSheet(mockExcelFile.Object, "file", "worksheet");
mockExcelFile
.Setup(x => x.Worksheet<Thing>(It.IsAny<string>()))
.Returns(ExcelQueryableOfThing());
// Act
List<Thing> rows = thingsSheet.GetRows();
// Assert
Assert.AreEqual(2, rows.Count); // Adam and Eva
}

Categories