Setup for testing a Linq query on a LinqToExcel IExcelQueryFactory - c#

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
}

Related

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.

Unit testing and mocking domain objects

I have a domain class, which looks like this:
public class Employee
{
public Guid EmployeeId { get; private set; }
public string Name { get; private set; }
public string Surname { get; private set; }
...
// other properties
public ICollection<Language> Languages { get; private set; }
= new List<Language>();
public ICollection<Skill> Skills { get; private set; }
= new List<Skill>();
public void AddLanguage(Language language)
{
if (language == null)
return;
Languages.Add(language);
}
public void DeleteLanguage(Guid languageId)
{
var languageToDelete = Languages
.SingleOrDefault(x => x.LanguageId == languageId);
if(languageToDelete == null)
throw new ArgumentException("Language entry doesn't exist.");
Languages.Remove(languageToDelete);
}
}
I would like to test given methods but I'm stuck.
I have:
[Fact]
public void AddLanguage_AfterCallWithValidObject_LanguagesCollectionContainsAddedObject()
{
var language = new Mock<Language>();
var employee = new Employee("Name", "Surname", ...);
employee.AddLanguage(language.Object);
Assert.Contains(employee.EmployeeLanguages, x => x.Language.Equals(language.Object));
}
[Fact]
public void DeleteLanguage_WhenLanguageWithGivenIdDoesntExist_ThrowArgumentException()
{
var languageToDelete = new Language("English");
var employee = new Mock<Employee>();
employee.Setup(x => x.Languages).Returns(new List<Languages>
{
new Language("Spanish"),
new Language("German")
});
employee.Object.DeleteLanguage(languageToDelete);
// Asserts here
}
In the first test I would like also assert that Languages.Add(skill) method was called but I have no idea how to do it.
Is it an elegant way to do it? I thought about mocking Add method but I'm not sure if it is a good idea.
In the second test I cannot simply mock Employee object as it is not an interface.
I thought about exposing Employee but I read I should not do that just for testing purpose.
How should I mock Languages property without exposing Employee as interface? Is it possible? Is it any good practice to do this kind of things?
Is my general concept for test these methods is okay? (I'm new in unit testing)
You should tests objects as "black box" without relying on implementation details. In your case implementation details is that Employee class uses ICollection.Add method.
And you definitely don't need to mock at all in your case.
Mock only dependencies which will make tests slow or very very very very complex to configure for the test.
[Fact]
public void AddLanguage_ShouldSaveGivenLanguage()
{
var language = new Language();
var employee = new Employee("Name", "Surname");
employee.AddLanguage(language);
var expectedLanguages = new[] { language };
employee.EmployeeLanguages.Should().BeEquivalentTo(expectedLanguages);
}
Use public API Employee class provide to setup it for the test (back box).
For testing DeleteLanguage add dummy languages through public API of the class.
[Fact]
public void DeleteLanguage_WhenLanguageExists_Remove()
{
var language1 = new Language("German");
var language2 = new Language("French");
var languageToDelete = new Language("English");
var employee = new Employee("Name", "Surname");
employee.AddLanguage(language1);
employee.AddLanguage(language2);
employee.AddLanguage(languageToDelete);
employee.DeleteLanguage(languageToDelete);
var expectedLanguages = new[] { language1, language2 };
employee.EmployeeLanguages.Should().BeEquivalentTo(expectedLanguages);
}
[Fact]
public void DeleteLanguage_WhenLanguageNotExists_ThrowException()
{
var language1 = new Language("German");
var language2 = new Language("French");
var notExistedLanguage = new Language("English");
var employee = new Employee("Name", "Surname");
employee.AddLanguage(language1);
employee.AddLanguage(language2);
Action delete = () => employee.DeleteLanguage(languageToDelete);
delete.Should()
.Throw<ArgumentException>()
.WithMessage("Language entry doesn't exist.");
}
Did you notice how cumbersome employee.EmployeeLanguages reads, you can rename property to just employee.Languages.
For readable assertions I used FluentAssertions library
For domain objects with very simple behavior and no dependencies, mocking isn't strictly needed. You can test Add simply with this:
//Arrange
var e = new Employee();
var l = new Mock<Language>();
//Act
e.AddLanguage(l.Object);
//Assert
Assert.IsTrue(e.Languages.Contains(l.Object));
Testing in this fashion you can achieve perfectly good code coverage and plenty of confidence that the Employee class works as designed.

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 and verify expression with Moq

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);
}
}
}

Calling a method twice with different values Unit testing using MOQ

I want to test a construct which calls a method within it twice to get two different values
public class stubhandler
{
public stubhandler()
{
string codetext = model.getValueByCode(int a,string b); // 1,"High" result Canada
string datatext = model.getValueByCode(int a,string b); // 10, "Slow" result Motion
}
}
To test the above i use a unit test class
[TestMethod]
public void StubHandlerConstructor_Test()
{
Mock<Model> objMock = new Mock<>(Model);
objMock.Setup(m => m.getValueByCode(It.IsAny<int>,It.IsAny<string>)).Returns("Canada");
objMock.Setup(m => m.getValueByCode(It.IsAny<int>,It.IsAny<string>)).Returns("Motion");
stubhandler classstubhandler = new stubhandler();
}
The above method pass but codetext and datatext contains same value Motion
i want them to set to
codetext = Canada
datatext = Motion
How can i achieve this?
I have tried objMock.VerifyAll() which fails the test ??
If using MOQ 4 one can use SetupSequence, else it can be done using a lambda
Using SetupSequence is pretty self explanatory.
Using the lambdas is not too messy. The important point to not it that the return value is set at the time that the setup is declared. If one just used
mockFoo.Setup(mk => mk.Bar()).Returns(pieces[pieceIdx++]);
the setup would always return pieces[0]. By using the lambda, the evaluation is deferred until Bar() is invoked.
public interface IFoo {
string Bar();
}
public class Snafu {
private IFoo _foo;
public Snafu(IFoo foo) {
_foo = foo;
}
public string GetGreeting() {
return string.Format("{0} {1}",
_foo.Bar(),
_foo.Bar());
}
}
[TestMethod]
public void UsingSequences() {
var mockFoo = new Mock<IFoo>();
mockFoo.SetupSequence(mk => mk.Bar()).Returns("Hello").Returns("World");
var snafu = new Snafu(mockFoo.Object);
Assert.AreEqual("Hello World", snafu.GetGreeting());
}
[TestMethod]
public void NotUsingSequences() {
var pieces = new[] {
"Hello",
"World"
};
var pieceIdx = 0;
var mockFoo = new Mock<IFoo>();
mockFoo.Setup(mk => mk.Bar()).Returns(()=>pieces[pieceIdx++]);
var snafu = new Snafu(mockFoo.Object);
Assert.AreEqual("Hello World", snafu.GetGreeting());
}
Moq documentation says you can simulate something like successive returns with Callback method:
var values = new [] { "Canada", "Motion" };
int callNumber = 0;
mock.Setup(m => m.getValueByCode(It.IsAny<int>(), It.IsAny<string>()))
.Returns((i,s) => values[callNumber])
.Callback(() => callNumber++);
This will do the trick, but it's not the most elegant solution. Matt Hamilton proposes much better one in his blog post, with clever use of queue:
var values = new Queue<string> { "Canada", "Motion" };
mock.Setup(m => m.getValueByCode(It.IsAny<int>(), It.IsAny<string>()))
.Returns(() => values.Dequeue());
Calling mock.Object.getValueByCode twice, will produce "Canada" and "Motion" strings respectively.

Categories