Moq Setup dont working, while trying to automate it - c#

Main Goal : Automatic Moq an entire DBContext
Current Problem: Setup donĀ“t work. It runs and adds the Setup but when you try to access the Data you get an "NotImplemented Exception"
The member 'IQueryable.Provider' has not been implemented on type 'DbSet 1Proxy_4' which inherits from 'DbSet 1'. Test doubles for 'DbSet 1' must provide implementations of methods and properties that are used.
My class
public abstract class MoqBase<T> where T : DbContext
{
public Mock<T> MockContext { get; private set; }
public void Mock()
{
MockContext = new Mock<T> { DefaultValue = DefaultValue.Mock };
MockContext.SetupAllProperties();
PrepareContext();
}
private void PrepareContext()
{
var propertyList = MockContext.Object.GetType().GetProperties();
var tablePropertyList = propertyList.Where(x => x.PropertyType.FullName.Contains("DbSet")).ToList();
foreach (var tableProperty in tablePropertyList)
{
var proxy = tableProperty.GetValue(MockContext.Object);
dynamic mockSet = ((dynamic)proxy).Mock;
AddTableSetup(mockSet);
}
}
public void AddTableSetup<TTable>(Mock<DbSet<TTable>> Mockset) where TTable : class
{
var list = new List<TTable>();
var data = list.AsQueryable();
Mockset.As<IQueryable<TTable>>().Setup(m => m.Provider).Returns(data.Provider);
Mockset.As<IQueryable<TTable>>().Setup(m => m.Expression).Returns(data.Expression);
Mockset.As<IQueryable<TTable>>().Setup(m => m.ElementType).Returns(data.ElementType);
Mockset.As<IQueryable<TTable>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator);
}
}
TestMoq which implements MoqBase
public class TestMoq : MoqBase<NetConPortalContext>//NetConPortalContext is my dbContext
{
public TestMoq() => Mock();
}
Try to access
static void Main()
{
var moq = new TestMoq();
var context = moq.MockContext.Object;
var test = context.User.FirstOrDefault();
}
Picture of Error and Setup in Debug

Related

AutoFixture multiple customization wont work

AutoFixture will not work with register and additional customize call. If I do only one of the two, it works. The whole behavior of customize feature is hard to understand for me. Is this works as designed?
Goal: Use the greediest constructor AND OmitAutoProperties for special class.
public interface IDataProvider { }
public class FileDataProvider : IDataProvider {}
public class TestClass
{
public TestClass() : this (new FileDataProvider()) { }
public TestClass(IDataProvider dataProvider) { } // should be used from AutoFixture
}
[Fact]
public void Method_State_Result()
{
var fixture = new Fixture();
fixture.Register(() => fixture.Build<TestClass>().OmitAutoProperties().Create());
var dc1 = fixture.Create<TestClass>(); // working
fixture.Customize(new AutoNSubstituteCustomization());
fixture.Customizations.Add(new MethodInvoker(new GreedyConstructorQuery()));
var dc2 = fixture.Create<TestClass>(); // crash with "AutoFixture was unable to create an instance from System.SByte*, most likely because it has no public constructor, is an abstract or non-public type"
var dc3 = fixture.Create<TestClass>();
}
A workaround would be to do the registration like this. But feels not like the right solution...
fixture.Register(() => new Fixture().Build<TestClass>().OmitAutoProperties().Create());
If I understood the question correctly, then the easiest option is to provide a custom factory that uses a specimen builder.
fixture.Customize<TestClass>(c => c
.FromFactory(new MethodInvoker(new GreedyConstructorQuery()))
.OmitAutoProperties());
Here is a sample test.
public class TestClass
{
public TestClass() : this(new FileDataProvider())
{
}
public TestClass(IDataProvider dataProvider)
{
DataProvider = dataProvider;
}
public string SomeString { get; set; }
public IDataProvider DataProvider { get; }
}
[Fact]
public void FooTest()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
fixture.Customize<TestClass>(c => c
.FromFactory(new MethodInvoker(new GreedyConstructorQuery()))
.OmitAutoProperties());
var mockProvider = fixture.Freeze<IDataProvider>();
var testObject = fixture.Create<TestClass>();
Assert.Null(testObject.SomeString);
Assert.Same(mockProvider, testObject.DataProvider);
}

NSubstitute, DbContext and a strange issue when trying to write a test

I have a nice extension method for mocking a DbSet:
public static class DbSetExtensions
{
public static DbSet<T> ToDbSet<T>(this IEnumerable<T> data) where T : class
{
var queryData = data.AsQueryable();
var dbSet = Substitute.For<DbSet<T>, IQueryable<T>>();
((IQueryable<T>)dbSet).Provider.Returns(queryData.Provider);
((IQueryable<T>)dbSet).Expression.Returns(queryData.Expression);
((IQueryable<T>)dbSet).ElementType.Returns(queryData.ElementType);
((IQueryable<T>)dbSet).GetEnumerator().Returns(queryData.GetEnumerator());
return dbSet;
}
}
Which I am trying to use in a context file like this:
public class DatabaseContextContext<T> where T: DatabaseContextContext<T>
{
public DatabaseContext DatabaseContext;
protected DatabaseContextContext()
{
DatabaseContext = Substitute.For<DatabaseContext>();
}
public T WhenListSucceeds<TEntity>(IList<TEntity> data) where TEntity : class
{
var dbSet = data.ToDbSet();
DatabaseContext.Set<TEntity>().Returns(dbSet);
return (T)this;
}
public T WhenGetSucceeds<TEntity>(TEntity entity) where TEntity : class
{
var dbSet = new List<TEntity> { entity }.ToDbSet();
DatabaseContext.Set<TEntity>().Returns(dbSet);
return (T)this;
}
}
When I run my test on this method, it fails:
public ActionResult<List<Formula>> ListFormulas(int id) =>
Ok(_databaseContext.Formulas.Where(m => m.AttributeId.Equals(id)).ToList());
with this error message:
System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.ObjectProxy_3' to type 'Microsoft.EntityFrameworkCore.Metadata.Internal.Model'.
So I tried to break it down a bit.
First, I changed my method to this:
public ActionResult<List<Formula>> ListFormulas(int id)
{
var s = _databaseContext.Formulas;
var x = _databaseContext.Formulas.ToList();
var t = _databaseContext.Formulas.Where(m => m.AttributeId.Equals(id)).ToList();
return Ok(t);
}
But when debugging, the code was not getting past the ToList() method. I was still getting the same issue. So I have changed my code to this:
public ActionResult<List<Formula>> ListFormulas(int id)
{
var p = _databaseContext.Set<Formula>();
var q = p.ToList();
var s = _databaseContext.Formulas;
var x = _databaseContext.Formulas.ToList();
var t = _databaseContext.Formulas.Where(m => m.AttributeId.Equals(id)).ToList();
return Ok(t);
}
The first 3 lines of code work, but as soon as it get's to the line var x = _databaseContext.Formulas.ToList(); it fails.
Does anyone have any idea why?
Here is the test:
[TestFixture]
public class ListShould
{
[Test]
public void ReturnList()
{
// Assemble
var services = GenericOrderProviderContext.GivenServices();
var provider = services.WhenCreateOrderProvider();
services.DatabaseContext.Attributes = new List<Attribute>().ToDbSet();
services.DatabaseContext.Set<Attribute>().ReturnsForAnyArgs(_ => new List<Attribute>().ToDbSet());
// Act
var result = provider.List();
// Assert
result.Failure.Should().BeFalse();
result.Result.Count().Should().Be(0);
}
}
I was able to reproduce your error when the db context .Formulas property wasn't configured. If you're using both .Set<Formula>() and .Formulas you'll need to configure both.
I did notice that your set up for the db set enumerator
((IQueryable<T>)dbSet).GetEnumerator().Returns(queryData.GetEnumerator());
cause some behaviour that I've seen before where only the first ToList() invocation returns a result. If you get that, you may need to reset the enumerator or use the Func<CallInfo, IEnumerator<Formula>> Returns overload.

Moq - Extracting Mock DataSet & Context to a Separate Class

I have a unit test which verifies that a function adds exactly one record to an Entity Framework dataset like so:
var internals = new Mock<DbSet<InternalTransaction>>();
internals.Setup(q => q.Create()).Returns(new InternalTransaction());
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
// Removed: set up some data for my test
mockDC.Object.DoSomeFunction(data);
internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
Since I have a lot of tests to do with this context, I'm trying to extract the mock stuff to a separate class, like so:
public static class DataContext_Creators
{
public static Mock<IDataContext> CreateMockContext()
{
var internals = CreateMockDataSet<InternalTransaction>();
var externals = CreateMockDataSet<ExternalTransaction>();
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
mockDC.Setup(q => q.ExternalTransactions).Returns(externals.Object);
return mockDC;
}
private static Mock<DbSet<T>> CreateMockDataSet<T>() where T : class, new ()
{
var mockDataSet = new Mock<DbSet<T>>();
mockDataSet.Setup(q => q.Create()).Returns(new T());
// some other stuff, Provider, GetEnumerator, etc
return mockDataSet;
}
}
... and change my test to:
mockContext = Common.DataContext_Creators.CreateMockContext();
context = mockContext.Object;
// Removed: set up some data for my test
context.Object.DoSomeFunction(data);
//internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
But now that I can't access "internals" anymore, how can I do the .Verify() statement? context.InternalTransactions won't work because that returns "internals.Object" (which it needs to for the method I'm testing to work).
From that object you may once again regain Mock object of it by using Mock.Get() method. Look at example:
public class Entity
{
public virtual int Id { get; set; }
public virtual int? ParentId { get; set; }
}
static void Main(string[] args)
{
Entity entity = Mock.Of<Entity>();
var mock = Mock.Get<Entity>(entity);
mock.Setup(e => e.ParentId).Returns(11);
var result = entity.ParentId;
// now result == 11
}
You could use Mock.Get method on your internals.Object
Create a new utility class with 2 properties:
Mock<IDataContext> DbContextMock
Mock<DbSet<InternalTransaction>> InternalTransMock
Have your Utility function return this new object so your test has access to both.

Preventing Autofixture from filling child collections

I'm using the latest version of Autofixture, and I'd like to prevent it from filling automatically child collections.
For example, I have a class Person that has a List property. I want all properties filled, except the list.
I tried using this customization :
public class RemoveMultiples : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is DictionarySpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is CollectionSpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is HashSetSpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
fixture.Customizations
.OfType<FilteringSpecimenBuilder>()
.Where(x => x.Specification is ListSpecification)
.ToList().ForEach(c => fixture.Customizations.Remove(c));
}
}
But it also prevents me from using .CreateMany().
edit: I can use .CreateMany(3) and it works.
Is there a setting somewhere that could let me autofill collections only when I need to?
edit2: Class person should look like this:
[Serializable]
public class Person
{
private ICollection<OtherClass> _otherClasses;
private string _something;
public virtual ICollection<OtherClass> OtherClasses
{
get { return _otherClasses; }
set { _otherClasses = value; }
}
}
Note that it's not always a Collection, but sometimes IList
Note2: I just realized that someone also removed the Customization for IEnumerable hence why the CreateMany() doesn't create anything.
Here's one way to do it.
Start by implementing a SpecimenBuilder that tells AutoFixture to skip assigning a value for collection property:
public class CollectionPropertyOmitter : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi != null
&& pi.PropertyType.IsGenericType
&& pi.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>))
return new OmitSpecimen();
return new NoSpecimen(request);
}
}
Then encapsulate that in a Customization:
public class DoNotFillCollectionProperties : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new CollectionPropertyOmitter());
}
}
The following tests now pass:
[Fact]
public void CreatePersonWithoutFillingCollectionProperty()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.Create<Person>();
Assert.Null(actual.OtherClasses);
}
[Fact]
public void CreateManyStillWorks()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.CreateMany<Person>();
Assert.NotEmpty(actual);
}
[Fact]
public void CreatListStillWorks()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.Create<List<Person>>();
Assert.NotEmpty(actual);
}
[Fact]
public void CreateCollectionStillWorks()
{
var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
var actual = fixture.Create<ICollection<Person>>();
Assert.NotEmpty(actual);
}

Rhino Mock, Mock list of interface

How can i Mock list of object in for loop
Here is the code:`
public class SearchResult<T>
{
private readonly ISearcher<T> _searcher;
private readonly IList<ISearchConfigurator> _configurators;
public SearchResult(ISearcher<T> searcher, IList<ISearchConfigurator> configurators)
{
_searcher = searcher;
_configurators = configurators;
}
public DomainSearchResult<T> FindInAllDomains()
{
DomainSearchResult domainSearchResults = new DomainSearchResult<T>();
foreach (var configurator in _configurators)
{
IList<T> results = _searcher.SearchAll(configurator);
domainSearchResults.Results.Add(_configurator.DomainName, results);
}
return domainSearchResults;
}
}`
the property result is declared in the DomainSearchResult class :
IDictionary<string,IList<T>> Results { get; set; }
then i tried the following:
[Test]
public void FindInAllDomains_ReturnsAllRecord()
{
//Arrange
var configuratorMock = MockRepository.GenerateStub<IList<ISearchConfigurator>>();
var searchMock = MockRepository.GenerateMock<ISearcher<NativeDs>>();
var searchRestul = new SearchResult<NativeDs>(searchMock, configuratorMock);
//Act
searchRestul.FindInAllDomains(); // calling test fail here
//Assert
searchMock.AssertWasCalled(x => x.SearchAll(null), opt => opt.IgnoreArguments());
}
Error is:
System.NullReferenceException : Object reference not set to an instance of an object.
Try this...
var list = new List<ISearchConfigurator>
(from x in Enumerable.Range(1, 100)
select MockRepository.GenerateMock<ISearchConfigurator>()
);

Categories

Resources