Moq EF 6 DBSet, Setup FirstOrDefault method - c#

I would like testing private method. When I setup FirstOrDefault method Moq thrown Exception. In my algorithm, I want check that, does my method properly create new objects.
See my code below.
//Arrange
var data = new List<TypeValue>();
var typeValueMockSet = new Mock<DbSet<TypeValue>>();
typeValueMockSet
.As<IList<TypeValue>>()
.Setup(m => m.GetEnumerator())
.Returns(data.GetEnumerator());
//throw the Error => Expression references a method that does not belong to the mocked object:
// m => m.FirstOrDefault<TypeValue>(It.IsAny<Expression`1>())
typeValueMockSet
.Setup(m => m.FirstOrDefault(It.IsAny<Expression<Func<TypeValue, bool>>>()))
.Returns(data.FirstOrDefault());
typeValueMockSet
.Setup(m => m.Add(It.IsAny<TypeValue>()))
.Returns((TypeValue vt) => vt)
.Callback((TypeValue vt) => data.Add(vt));
var mockContext = new Mock<EngineeringWorkEntities>();
mockContext.Setup(m => m.TypeValues).Returns(typeValueMockSet.Object);
int counter = 0;
mockContext
.Setup(m => m.SaveChanges())
.Returns(0)
.Callback(() => data
.ForEach(
(item) =>
{
item.Id = counter;
counter++;
}));
//Act
IMakro makroDateGenerate = new MakroDataGenerate(mockContext.Object);
var pObj = new PrivateObject(makroDateGenerate);
int r1 = (int)pObj.Invoke("GetTypeValueId", "0,2% k/k"); //2

You cannot mock FirstOrDefault because it is an extension method. It doesn't belongs to List<T> or anything else.

You cannot test private methods other than by using Reflection in the unit tests. This is very cumbersome. You should test the public interface anyway.
Either make the method public or internal. If you make it internal, you can allow the unit test project to see it by the use of the InternalsVisibleToAttribute.
[assembly:InternalsVisibleTo("MyUnitTestProject")]

Related

C# xUnit Mock SetUp method returns null when Test run

I am working on .NET 5 automation test, I have created mock object using fixture which I can in debugging and configure setup method for mock return but getting null output, not sure what I am missing. In same test I have create mock method for other classes and it did worked.
var paidParkingTransactionsMoq = fixture.CreateMany<PaidParkingTransactionClientModel>(5);
fixture.Customize<PaidParkingTransactionClientModel>(c => c
.With(x => x.SiteId, siteId)
.With(x => x.Vrm, vrm)
.With(x => x.TransactionFromDateUtc, exemptionStartDateTime)
.With(x => x.TransactionToDateUtc, exemptionEndDateTime)
);
var paidParkingTransactionMoq = fixture.CreateMany<PaidParkingTransactionClientModel>(1);
var PayByPhoneTransactions = paidParkingTransactionsMoq.Union(paidParkingTransactionMoq).ToList();
payByPhoneLoopupMoq.Setup(x => x.GetLatestTransactionAfterSync(machineMoq.ToList(), vrm)).ReturnsAsync(PayByPhoneTransactions);
Actual class
public class PayByPhoneExtensions
{
public async Task<List<PaidParkingTransactionClientModel>> GetLatestTransactionAfterSync(List<MachineDataView> machines, string vrm)
{
//remain code here
}
Error
found the answer
payByPhoneLoopupMoq.Setup(x => x.GetLatestTransactionAfterSync(It.IsAny<List<MachineDataView>>(), vrm)).ReturnsAsync(PayByPhoneTransactions);

Moq Setup Adding With Same "Filter" instead of overwriting

I am trying to mock a DbSet<> in Moq where I can add to the list of entities in the DbSet<>. In other words, a mutable DbSet<>.
I have some extension methods written for this, but have distilled the problem down into a single test.
I thought in Moq if you Setup the same call with the same parameters (filter), the Setup is replaced?
But, yet, this below unit test shows that it is added?
See 'below throws "Expected collection to contain 1 item(s), but found 2."'
[Fact]
public void Add2Test()
{
var contextMock = new Mock<IDbContext>();
List<MyEntity> data = new List<MyEntity>(){new MyEntity()};
var queryable = data.AsQueryable();
var mockDbSet = new Mock<DbSet<MyEntity>>();
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(0);
contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
// let's do it again
data = new List<MyEntity>() { new MyEntity() };
queryable = data.AsQueryable();
mockDbSet = new Mock<DbSet<MyEntity>>();
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
// below throws "Expected collection to contain 1 item(s), but found 2."
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
}
From my observations writing libraries such as EntityFrameworkCore.Testing, MemoryCache.Testing etc, Moq does not replace/override existing setups that are the same.
Though it's a Moq implementation detail, currently if you setup the same expression more than once the last setup added will be used.
void Main()
{
var mock = new Mock<IFoo>();
mock.Setup(x => x.Bar()).Returns("A");
mock.Setup(x => x.Bar()).Returns("B");
var mocked = mock.Object;
Console.WriteLine(mocked.Bar());
Console.WriteLine(mock.Setups.Select(x => x.ToString()));
}
public interface IFoo
{
public string Bar();
}

Unit testing a specific MongoDb FilterDefintion in C# with Moq

Trying to unit test the following MongoDb update function in C#.
var update = Builders<InvestorMongoDao>.Update
.Set(x => x.EmailAddress, command.EmailAddress);
await this.myDatabase.Users
.UpdateOneAsync(x => x.UserId == userId), update)
.ConfigureAwait(false);
I can easily check whether this function is called with a generic filter:
this.mockCollection
.Verify(x => x.UpdateOneAsync(It.IsAny<FilterDefinition<MyDao>>(),
It.IsAny<UpdateDefinition<MyDao>>(),
It.IsAny<UpdateOptions>(),
It.IsAny<CancellationToken>()));
However, I want to try and verify that it's being called with the expected parameter. I cannot seem to find a way to extract the parameter I want to check from FilterDefinition. I have tried this:
var foo = Builders<MyDao>.Filter.Eq("UserId", expectedUserId);
this.mockCollection
.Verify(x => x.UpdateOneAsync(It.Is<FilterDefinition<MyDao>>(a => a == foo),
It.IsAny<UpdateDefinition<MyDao>>(),
It.IsAny<UpdateOptions>(),
It.IsAny<CancellationToken>()));
But the test states the invocation is not performed. What am I doing wrong?
It appears you can approximate what's needed here by using Render.
var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<MyDao>();
var expectedFilter = Builders<MyDao>.Filter.Eq("UserId", existingInvestor2.InvestorId);
this.mockCollection
.Verify(x => x.UpdateOneAsync(It.Is<FilterDefinition<MyDao>>(a => a.Render(documentSerializer, serializerRegistry) == expectedFilter.Render(documentSerializer, serializerRegistry)),
It.IsAny<UpdateDefinition<MyDao>>(),
It.IsAny<UpdateOptions>(),
It.IsAny<CancellationToken>()));

How to mock Elasticsearch .Net client?

I am using Elasticsearch .Net Client 6.x, and I have some code like:
if(this.elasticClient.IndexExists("indexName").Exists){
// do something
}
this.elasticClient.CreateIndex(
newIndex,
x => x.Settings(s => s.NumberOfShards(1)).Mappings(ms => ms.Map<T>(m => m.AutoMap())));
var searchResponse = client.Search<dynamic>(
s => s.AllTypes()
.Index(
new[] { "indexName1", "indexName"}).IgnoreUnavailable().Size(size).From(from).Query(
q => q.Bool(b => b.Must(m => m.SimpleQueryString(c => c.Query(query).Lenient().AnalyzeWildcard())))));
Now in my unit test, I'd like to test the exact descriptor passed to each method, how can I do this?
var existsResponse = new Mock<ExistsResponse>();
existsResponse.Setup(x => x.Exists).Returns(false); // Oops: can't do this since Exists is not virtual, abstract
this.elasticClient.Setup(x => x.IndexExists("indexName", null)).Returns(existsResponse.Object);
this.elasticClient.Verify(
x => x.CreateIndex("IndexName", It.Is<Func<CreateIndexDescriptor, ICreateIndexRequest>>(x => /*what goes here??*/)),
Times.Once);
this.elasticClient.Verify(
x => x.Search<dynamic>(It.Is<Func<SearchDescriptor<dynamic>>>(x => /*what goes here??*/)),
Times.Once);
Should I just simply wrap the elasticClient in a class and implement every method I used, and pass it as dependency injection?

Omitting a specific field with CreateMany from AutoFixture

I want to create "many" instances of foo :
var fixture = new Fixture();
var expectedFoos = fixture.CreateMany<Foo>();
The problem is, Foo is an Entity Framework entity, with relations that I don't want to create. If I needed only one instance, I could do that :
var fixture = new Fixture();
var expectedFoo = fixture.Build<Foo>()
.Without(foo => foo.Relation1);
.Without(foo => foo.Relation2);
But how can I easily create multiple instances satisfying this condition ? I've read about specimen builders but it seems really overkill here.
I'm looking for something as simple as that (doesn't compile because BuildMany doesn't exist) :
var fixture = new Fixture();
var expectedFoos = fixture.BuildMany<Foo>()
.Without(foo => foo.Relation1);
.Without(foo => foo.Relation2);
That's what Customize is for:
var fixture = new Fixture();
fixture.Customize<Foo>(o => o
.Without(foo => foo.Relation1)
.Without(foo => foo.Relation2));
var expectedFoos = fixture.CreateMany<Foo>();
Using Customize is definitely the right answer. However, just for the sake of documentation, Build will work too:
var expectedFoos = fixture.Build<Foo>()
.Without(foo => foo.Relation1)
.Without(foo => foo.Relation2)
.CreateMany();

Categories