I'm attempting to mock and setup chained methods using Moq.
Here is the method I am trying to mock:
TeamMember teamMember = _unitOfWork
.TeamMembers
.Query()
.ToList()
.Where(t => t.AssociationCode.ToString() == code
&& Crypto.EncryptStringAES(t.Id.ToString(), sharedSecret) == hash)
.SingleOrDefault();
and here is where I attempt to mock it:
var unitOfWorkMock = new Mock<IUnitOfWork>();
var iQueryableMock = new Mock<IQueryable<TeamMember>>();
var iToListMock = new Mock<List<TeamMember>>();
var whereMock = new Mock<IList<TeamMember>>();
var singleMock = new Mock<IEnumerable<TeamMember>>();
unitOfWorkMock
.Setup(u => u.TeamMembers
.Query())
.Returns(iQueryableMock.Object);
iQueryableMock
.Setup(i => i.ToList())
.Returns(iToListMock.Object); //This line throws the error
whereMock
.Setup(w =>
w.Where(It.IsAny<Func<TeamMember, bool>>()))
.Returns(singleMock.Object);
singleMock
.Setup(s =>
s.SingleOrDefault())
.Returns(new TeamMember()
{
Email = "Test#TeamMember.com"
});
When I run this test it gives me this error:
Expression references a method that does not belong to the mocked object: i => i.ToList<TeamMember>()
I have looked at this question already and have tried to do something similar, but I must be missing something.
I am new to this, so if anyone can help me out it will be greatly appreciated.
Your method chain mocking looks fine, but your problem is that ToList is an extension method, which Moq cannot mock.
Related
I am trying to mock HttpRequestBase and HttpSessionStateBase objects and test my code with Moq mocking framework.
This is the relevant part of my setup.
_httpSessionStateBase = _mockRepository.Create<HttpSessionStateBase>();
_motorWebSession = new MotorWebSession
{
PersonaIdentifier = Guid.NewGuid(),
NameIdentifier = Guid.NewGuid(),
MiCurrentPageId = Guid.NewGuid(),
MiSessionId = Guid.NewGuid(),
};
_httpSessionStateBase.SetupGet(e => e.Count).Returns(1);
var keysCollection = new NameValueCollection { { "MotorSession", "MotorSession" } };
_httpSessionStateBase.SetupGet(e => e.Keys).Returns(keysCollection.Keys);
_httpSessionStateBase.Object[0] = _motorWebSession;
_httpSessionStateBase.Object["MotorSession"] = _motorWebSession;
_httpContextBase = _mockRepository.Create<HttpContextBase>();
_httpContextBase.SetupGet(h => h.Session).Returns(_httpSessionStateBase.Object);
In the current implementation this code is called within a test.
var webSession = _httpContext.Current.Session;
var sessionObject = webSession.Keys.Cast<string>()
.Where(w => webSession[w] is WebSessionBase)
.Select(s => webSession[s])
.ToList().FirstOrDefault();
During the Where clause sessionObject results into null which prevents any other subsequent code to run correctly. Is there something wrong I am doing with the setup? Or could the code be altered to work for this setup? It worked with Rhino.Mocks but I am trying to change it to Moq.
Instead of _httpSessionStateBase.Object["MotorSession"] = _motorWebSession; call _httpSessionStateBase.Setup( s => s["MotorSession"]).Returns(_motorWebSession);. Moq mocked objects can't be assigned directly even through index using the [] operator. The correct way to do that is to make a setup.
I'm trying to mock AnyAsync method in my repository with below codes but repository always returns false.
The signature of AnyAsync is:
Task<bool> AnyAsync<TEntity>(Expression<Func<TEntiry, bool>> predicate)
I tried the following setups:
1:
mockCustomerRepository.Setup(r => r.AnyAsync(c => c.Email == "some#one.com"))
.ReturnsAsync(true);
2:
Expression<Func<CustomerEntity, bool>> predicate = expr =>
expr.CustomerPerson.Email == "some#one.com";
mockCustomerRepository.Setup(r => r.AnyAsync(It.Is<Expression<Func<CustomerEntity, bool>>>
(criteria => criteria == predicate))).ReturnsAsync(true);
3:
mockCustomerRepository.Setup(r => r.AnyAsync(It.IsAny<Expression<Func<CustomerEntity, bool>>>()))
.ReturnsAsync(true);
My test:
public class Test
{
Mock<ICustomerRepository> mockCustomerRepository;
public Test()
{
mockCustomerRepository = new Mock<ICustomerRepository>();
}
[Fact]
public async Task CustomerTest()
{
var customer = ObjectFactory.CreateCustomer(email: "some#one.com");
var sut = new CustomerService(mockCustomerRepository.Object);
var result = await sut.ValidateCustomerAsync(customer);
.
.
.
}
}
My CustomerService.ValidateCustomerAsync method:
public async Task<OperationResult> ValidateCustomerAsync(CustomerEntity customer)
{
var errors = new List<ValidationResult>();
if (await _repository.AnyAsync(c => c.Email == customer.Email))
errors.Add(new ValidationResult("blah blah")));
I've also read this but it doesn't work too.
The following snippet shows the correct way to mock your AnyAsync method:
[TestMethod]
public async Task TestMethod1()
{
var fakeCustomerRepo = new Mock<ICustomerRepository>();
var foo = false;
fakeCustomerRepo.Setup(repository => repository.AnyAsync(It.IsAny<Expression<Func<CustomerEntity, bool>>>()))
.Callback<Expression<Func<CustomerEntity, bool>>>(
expression =>
{
var func = expression.Compile();
foo = func(new CustomerEntity() {Email = "foo#gmail.com"});
})
.Returns(() => Task.FromResult(foo));
var customer = new CustomerEntity() {Email = "foo#gmail.com"};
var result = await fakeCustomerRepo.Object.AnyAsync<CustomerEntity>(c => c.Email == customer.Email);
Assert.IsTrue(result);
customer = new CustomerEntity() { Email = "boo#gmail.com" };
result = await fakeCustomerRepo.Object.AnyAsync<CustomerEntity>(c => c.Email == customer.Email);
Assert.IsFalse(result);
}
using the above setup you can verify your predicate which is part of your unit behavior.
I think you're running into the difficulties of matching predicates. Funcs or expressions of Funcs use reference-equality, so just using == to compare the two instances isn't going to work. (As a general rule, if you can't get predicate1.Equals(predicate2) to return true, Moq's argument matchers aren't going to match.)
This is a little unorthodox, but I refer you to my answer to a similar question for FakeItEasy matchers, which in turn points you at a number of techniques for validating predicates.
All I can see that should cause this problem are two options:
1. The repository method does not come from an interface that you should mock to return the desired value, as it is not marked with virtual.
2. The types (TEntity) you use in method do not match when you are using the moq.
AnyAsync<TEntity>(Expression<Func<TEntity, bool>>
as you can setup for let's say MemberEntity and call the ValidateCustomerAsync with a CustomerEntity.
Maybe I am wrong but, but as far as I have read for methods that return only a Task, .Returns(Task.FromResult(default(object))) can and should be used.
So in your case it would be mocksCustomerRepository.Setup(r => r.AnyAsync(c => c.Email == "some#one.com")).Returns(Task.FromResult(true));
I want to test that a method adds a record to a DBSet under a certain condition:
public static void AddTriggeredInternalTransactions(IDataContext dc, ExternalTransaction transaction)
{
if (transaction [meets condition A])
dc.InternalTransactions.CreateInverseTransaction(transaction);
// do other stuff under other conditions
}
private static void CreateInverseTransaction(this IDbSet<InternalTransaction> transactions, ExternalTransaction from)
{
var internalTransaction = transactions.Create();
from.CopyToInternalTransaction(internalTransaction);
transactions.Add(internalTransaction);
}
Now, I already have tests for CopyToInternalTransaction(). I just need to call AddTriggeredInternalTransactions() and verify that [condition A] results in the new record being added).
I started with http://msdn.microsoft.com/en-us/data/dn314429.aspx, then used other Google and StackOverflow searches. Before tackling my "real" test, I'm trying to do a simple test just to verify whether a record has been added to a dataset, but I'm stuck on this. Can anyone point out my flaw(s)?
var internals = new Mock<DbSet<InternalTransaction>>();
var theData = new List<InternalTransaction>().AsQueryable();
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.Provider).Returns(theData.Provider);
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.Expression).Returns(theData.Expression);
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.ElementType).Returns(theData.ElementType);
internals.As<IQueryable<InternalTransaction>>().Setup(m => m.GetEnumerator()).Returns(theData.GetEnumerator());
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
mockDC.Setup(q => q.InternalTransactions.Create()).Returns(new InternalTransaction());
mockDC.Setup(q => q.InternalTransactions.Add(It.IsAny<InternalTransaction>()));
var it = mockDC.Object.InternalTransactions.Create();
it.Id = "123";
mockDC.Object.InternalTransactions.Add(it);
internals.Verify(e => e.Add(It.Is<InternalTransaction>(d => d.Id == "123")), Times.Once());
//or: Assert.Equal(1, mockDC.Object.InternalTransactions.Count());
This test fails with: Expected invocation on the mock once, but was 0 times: e => e.Add(It.Is(d => d.Id == "123")) No setups configured. No invocations performed.
The Assert statement, if used instead, fails with a NotImplementedException: "The member IQueryable.Provider has not been implemented on type DbSet~1Proxy_1 which inherits from DbSet1. Test doubles for DbSet1 must provide implementations of methods and properties that are used."
After comments by Adam and Stuart plus further experimentation, I was able to reduce my test case to the following working test case:
var internals = new Mock<DbSet<InternalTransaction>>();
var mockDC = new Mock<IDataContext>();
mockDC.Setup(q => q.InternalTransactions).Returns(internals.Object);
internals.Setup(q => q.Create()).Returns(new InternalTransaction());
var transaction = new ExternalTransaction { [set criteria for Condition A] };
SomeBusinessObject.AddTriggeredInternalTransactions(mockDC.Object, transaction);
// verify the Add method was executed exactly once
internals.Verify(e => e.Add(It.IsAny<InternalTransaction>()), Times.Once());
How do I mock something that is - Expression> using Moq?
I'm trying to mock a call to my repo layer that takes in a LINQ Expression for constructing a query. I'm trying the below syntax but it fails. The SearchFor method doesn't get called.
var array = new Employee[1];
array[0] = new Employee() { ID = 1234, Name = "Test" };
MockEmployeeRepo.Setup(x => x.SearchFor(It.IsAny<Expression<Func<Employee, bool>>>()))
.Returns(array.AsQueryable);
var list = EmployeeService.GetEmployees("Test");
MockEmployeeRepo.Verify(x => x.SearchFor(x1 => x1.Name == "Test"), Times.Once());
Assert.AreEqual("Test", list[0].Name);
Here the GetEmployees method looks like below.
public IEnumerable<Employee> GetEmployees(string name)
{
return repo.SearchFor(x => x.Name == name);
}
Moq does not supports with Expression function so here is the best solution. Use this nuget package Moq.Expression
// import namespace
using MoqExpression;
// it will work
MockEmployeeRepo.Setup(x => x.SearchFor(MoqHelper.IsExpression<Employee>(s => s.Name.Equals("Test")))).Returns(array.AsQueryable);
For more documentation: https://github.com/ovaishanif94/Moq.Expression
I'm new to Moq and I'm trying to Mock my repository.
The method I'm Writing a unit test for is calling the repository like this:
var paymentState = _agreementPaymentStateRepository.SingleOrDefault(
s => s.Agreement.ID == agreementID);
I'm trying to set up my moq like this:
_agreementPaymentStateRepositoryMock
.Setup(m => m.SingleOrDefault(s => s.AgreementID == 1))
.Returns(AgreementPayMentStateMocks.GetOne);
I pass my mocked repository to the class but the paymentState variable is null after the call is made. (I would gladely skip specifying the expression as well).
Any help is much appreciated.
public PaymentState GetPaymentState(int agreementID)
{
try
{
_log.AgreementPaymentStateServiceGetStateStart(agreementID);
var paymentState =
_agreementPaymentStateRepository.SingleOrDefault(s => s.Agreement.ID == agreementID);
var stateToGet = MapStateToGet(paymentState);
_log.AgreementPaymentStateServiceGetStateReturn(agreementID, paymentState.LatestStatus);
return stateToGet;
}
catch (Exception ex)
{
_log.ServiceException(ex.ToString());
throw;
}
}
and the test:
var paymentState = AgreementPayMentStateMocks.GetPayMentState();
_agreementPaymentStateRepositoryMock.Setup(m => m.SingleOrDefault(s => s.AgreementID == 1)).Returns(AgreementPayMentStateMocks.GetOne);
var service = new AgreementPaymentStateService(_agreementPaymentStateRepositoryMock.Object, _log.Object);
var result = service.GetPaymentState(1);
_agreementPaymentStateRepositoryMock.Verify(m => m.Match(aps => aps.SingleOrDefault(s => s.AgreementID == 1)), Times.Exactly(1));
Instead of having a concrete predicate in the SingleOrDefault call, use Moq's It.IsAny<T> method:
_agreementPaymentStateRepositoryMock
.Setup(m => m.SingleOrDefault(It.IsAny<Expression<Func<bool,PaymentState>>>()))
.Returns(AgreementPayMentStateMocks.GetOne);