Mock for several predicates - c#

I create a mock object with one method
IMyIterface dosGuard = Mock.Of<IMyIterface >(
dg =>
dg.IsMethod1(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>()) == false
);
I would like to specify the predicate for other method also :
dg.IsMethod2(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>()) == false
How can I do it for both methods together?

Yes, you actually can factory build the entire object's structure with Mock.Of<T>() -- it just appears a little quirky at first:
interface IInterface
{
int IntMethod();
string StringMethod();
}
var instance = Mock.Of<IInterface>(ifc =>
ifc.IntMethod() == 1 &&
ifc.StringMethod() == "Hello");
It uses boolean as MemberAssignment, but aside from that, it would read get me a Mock of IInterface, with an IntMethod returning 1 and a StringMethod returning "Hello". Also the It.IsAny<TType>() for parameters works in the predicate, as well as nested Mock.Of<T> calls.
Once you get going though, it becomes much cleaner, and one can spin up static methods for assignment/updating root test scenarios : i.e. take 'optimal' model and tweak a few fields, without having to re-type the entire model.

If you want to setup multiple things on your mock object you can't* use the Mock.Of<T> factory method, you need to setup the mock object yourself:
var dosGuardMock = new Mock<IMyInterface>();
dosGuardMock.Setup(dg => dg.IsMethod1(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
dosGuardMock.Setup(dg => dg.IsMethod2(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
var dosGuard = dosGuardMock.Object;
*Alternatively, you can use the factory method, and use the static Mock.Get method to modify the instance created by the factory method:
var dosGuard = new Mock.Of<IMyInterface>();
Mock.Get(dosGuard).Setup(dg => dg.IsMethod1(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
Mock.Get(dosGuard).Setup(dg => dg.IsMethod2(It.IsAny<IPAddress>(), It.IsAny<string>(), It.IsAny<string>())).Returns(false);
However, I prefer the first example, because it draws an explicit difference between the Mock<T> instance and the "mock" T instance.

Related

Mock SignalR hub for testing dependent class

I'm trying to instantiate a class that handles a bunch of functionality, and is constructed using dependency injection. I mock two of my parameters, and the third is an in-memory database context. Now when asserting, it's throwing an error on the mockClientProxyParticipants.Verify() line:
System.NotSupportedException : Invalid verify on an extension method: proxy => proxy.SendAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>())
It is virtually impossible to not call the function, and calling Verify() with Times.Never() as parameter doesn't change anything.
I tried setting up the Linq argument of Verify() using normal strings like for mockClientProxyResults.Verify(), I tried using It.Is<string>(s => s == "some string") and I tried It.IsAny<string>().
I honestly don't understand what's wrong right now. Here's my test code, let me know if you want to see more:
var mockHub = new Mock<IHubContext<VoteHub>>();
var mockClients = new Mock<IHubClients>();
var mockClientProxyParticipants = new Mock<IClientProxy>();
var mockClientProxyResults = new Mock<IClientProxy>();
mockClients.Setup(clients => clients.Group("Participants")).Returns(mockClientProxyParticipants.Object);
mockClients.Setup(clients => clients.Group("Results")).Returns(mockClientProxyResults.Object);
mockHub.Setup(hub => hub.Clients).Returns(mockClients.Object);
var activeQuestionManagerMock = new Mock<IActiveQuestionManager>();
activeQuestionManagerMock.Setup(x => x.GetActiveQuestion())
.Returns(new ActiveQuestionModel(options));
QuestionHandler qm = new QuestionHandler(new VoteDbContext(options), mockHub.Object, activeQuestionManagerMock.Object);
//Act
qm.Ask(question);
//Assert
mockClientProxyParticipants.Verify(proxy => proxy.SendAsync(It.IsAny<string>(/*s => s == "AskQuestion"*/), It.IsAny<string>(/*s => s == qwaJSON*/), It.IsAny<CancellationToken>()), Times.Once());
mockClientProxyResults.Verify(proxy => proxy.SendAsync("UpdateCurrentQuestionProgress", It.IsAny<ActiveQuestionModel>(), default(CancellationToken)), Times.Once());
Turns out I misunderstood the error message and the issue is that IClientProxy.SendAsync() is an extension method, and Moq apparently doesn't like that. It's possible to use SendCoreAsync() instead, but you'll always have to pass an array as parameter, even if you want to send just one object or don't want to send any data at all.
credit to NKosi (see question comments)

Moq Entity Frameworks ExecuteSQLCommand

I've read that when using moq you cannot mock a non-virtual function. I've also read that this should be possible now.. Is that true?
If so, then I'd like to mock the following query:
DatabaseContext.Database.ExecuteSqlCommand(updateQuery, newValue);
I'm overriding the Context in my test as so
DAL.Context.DatabaseContext = mockContext.Object;
I've tried this setup, but it seems the query stills goes agains my regular db
mockContext.Setup(c => c.Set<AppSalesAndResult>()).Returns(mockBudgetData.Object);
Any ideas, could perhaps the executesqlcommand be replaced with something else so that the row above would catch any udpates to the set? I use executesqlcommand due to performance reasons when updating multiple rows at once. Regular EF is too slow
UPDATE:
Reading the following post, How to Moq Entity Framework SqlQuery calls I wonder if a similar implementation would work for ExecuteSQLCommand...
What I have done to being able to Mock ExecuteSqlCommand, which is not possible to do in DataBase class, was to create the same method in my DbContext inheritance but this time virtual, and call the Database.ExecuteSqlCommand
public class MyDbContext : DbContext
{
public virtual int ExecuteSqlCommand(string sql, params object[] parameters)
{
return Database.ExecuteSqlCommand(sql, parameters);
}
public virtual int ExecuteSqlCommand(TransactionalBehavior transactionalBehavior, string sql, params object[] parameters)
{
return Database.ExecuteSqlCommand(transactionalBehavior, sql, parameters);
}
Then I changed my business code to call this created method (Not Database method):
DatabaseContext.ExecuteSqlCommand(updateQuery, newValue);
Then, it works
It is possible to mock ExecuteSqlCommand. It is however not straightforward.
Being an extension method you have to mock the internals. It ends up creating a RawSqlCommand and invoking ExecuteNonQuery on an IRelationalCommand. It gets further complicated as the extension method creates new objects to do the actual work, as well as there being is no interface for RawSqlCommand or DatabaseFacade, you've got to mock the concrete classes.
I ended up writing EntityFrameworkCore.Testing as there isn't anything else around that can do all the mocks (FromSql, ExecuteSqlCommand, DbQuery, the relational stuff that the in-memory provider can't do). Save yourself some time as the mocks are involved, I certainly would have used an existing package if there was one when I was looking.
If you do want to roll your own the mock set up for ExecuteSqlCommand/ExecuteSqlCommandAsync looks like the following:
var relationalCommandMock = new Mock<IRelationalCommand>();
relationalCommandMock
.Setup(m => m.ExecuteNonQuery(It.IsAny<IRelationalConnection>(), It.IsAny<IReadOnlyDictionary<string, object>>()))
.Returns((IRelationalConnection providedConnection, IReadOnlyDictionary<string, object> providedParameterValues) => executeSqlCommandResult);
relationalCommandMock
.Setup(m => m.ExecuteNonQueryAsync(It.IsAny<IRelationalConnection>(), It.IsAny<IReadOnlyDictionary<string, object>>(), It.IsAny<CancellationToken>()))
.Returns((IRelationalConnection providedConnection, IReadOnlyDictionary<string, object> providedParameterValues, CancellationToken providedCancellationToken) => Task.FromResult(executeSqlCommandResult));
var relationalCommand = relationalCommandMock.Object;
var rawSqlCommandMock = new Mock<RawSqlCommand>(MockBehavior.Strict, relationalCommand, new Dictionary<string, object>());
rawSqlCommandMock.Setup(m => m.RelationalCommand).Returns(relationalCommand);
rawSqlCommandMock.Setup(m => m.ParameterValues).Returns(new Dictionary<string, object>());
var rawSqlCommand = rawSqlCommandMock.Object;
var rawSqlCommandBuilderMock = new Mock<IRawSqlCommandBuilder>();
rawSqlCommandBuilderMock
.Setup(m => m.Build(It.IsAny<string>(), It.IsAny<IEnumerable<object>>()))
.Returns((string providedSql, IEnumerable<object> providedParameters) => rawSqlCommand);
var rawSqlCommandBuilder = rawSqlCommandBuilderMock.Object;
var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IConcurrencyDetector)))).Returns((Type providedType) => Mock.Of<IConcurrencyDetector>());
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IRawSqlCommandBuilder)))).Returns((Type providedType) => rawSqlCommandBuilder);
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IRelationalConnection)))).Returns((Type providedType) => Mock.Of<IRelationalConnection>());
var serviceProvider = serviceProviderMock.Object;
var databaseFacadeMock = new Mock<DatabaseFacade>(MockBehavior.Strict, mockedDbContext);
databaseFacadeMock.As<IInfrastructure<IServiceProvider>>().Setup(m => m.Instance).Returns(serviceProvider);
var databaseFacade = databaseFacadeMock.Object;
Mock.Get(mockedDbContext).Setup(m => m.Database).Returns(databaseFacade);
executeSqlCommandResult is the expected integer to return. You could use a callback to apply any operation said sql command performs on your data source.
Note that I am passing the mocked db context to the database facade mock constructor then performing another Moq set up on the mocked database, I get away with this as I have already performed a set up on the DbContext Database property as part of mocking the db context. I have observed test success with an inline new instance so I don't think it matters, just in my case I didn't want to spin up another instance.

Is there any better way of writing this test with Moq?

I have a private method which is being called in a method I am testing.I want to verify the correct parameters are being passed to this private method. I have written the following setup in Moq which will test what I want, however it doesn't really allow me to follow the Arrange, Act, Assert pattern.
Is there any way I can perform a similar test where by the assert can appear with all of my other asserts? At the moment the code below lives within the Arrange.
myClass.Setup(
x =>
x.myMethod(
It.IsAny<Person>>(),
It.IsAny<string>(),
It.IsAny<Person>(),
It.IsAny<ICollection<string>>(),
It.IsAny<ICollection<string>>(),
It.IsAny<bool>())).Callback
<Person, string, Person, Person, ICollection<string>, bool>(
(a, b, c, d, e, f) =>
{
Assert.AreEqual("NameA", a.Name);
Assert.AreEqual("StringB", b);
Assert.AreEqual("NameC", c.Name);
Assert.AreEqual(2, d);
var dList = d.ToList().OrderBy(x => x.Name);
Assert.AreEqual("PersonA", dList[0].Name)
Assert.AreEqual("PersonB", dList[1].Name);
});
I should say, I am aware that you can perfom a verify to check whether a method has been called with certain inputs, however I am not aware of any way of matching the ICollection params.
If you are using those assertions to check the parameters, you can do it in your setup. If your mock uses strict behavior, it will fail if a parameter doesn't match the predicate.
// declare your mock with strict behavior
myClass.Setup(
x =>
x.myMethod(
It.Is<Person>(person => person.Name == "NameA"),
"Stringb",
It.Is<Person>(person => person.Name == "NameC"),,
It.Is<ICollection<string>>(coll =>{
//your other validations
}),
It.IsAny<ICollection<string>>(),
It.IsAny<bool>()));
Purpose of unit tests is to verify that your class behaves as expected. You should exercise class via its public interface and check following things:
class state changes
returned results
calls to dependencies
Other stuff has no value while class behaves as expected. You can refactor your class and make that private method in-line.

moq and parameters matching

I'm struggeling with using moq and validating parameters passed to the methods of mocked interface. I have a code like:
MockRepository mockRepository = new MockRepository(MockBehavior.Default);
Mock<IConfigurationUpdater> workerInstanceMock = mockRepository.Create<IConfigurationUpdater>();
Mock<IConfiguration> configurationMock = mockRepository.Create<IConfiguration>();
configurationMock.Setup(t => t.Folder).Returns("Folder");
configurationMock.Setup(t => t.FileName).Returns("FileName");
workerInstanceMock
.Setup(
x => x.DoSomeWork(
It.Is<string>(
t => t == Path.Combine(configurationMock.Object.Folder, configurationMock.Object.FileName))))
.Verifiable("DoSomeWork not properly called");
mockRepository.VerifyAll();
The problem is that inside the lambda expresion generated for "It.Is", all properties of configurationMock (which were setup previously) are null. (if I would take that "Path.Combine" into a string, it would all work just fine).
In this exact case, the "Path.Combine" is failing because it received null parameters.
How should I properly use mocks and validate that my interface is called with the correct parameters.
Thanks,
florin
I think you need to use moq properties that will automatically start tracking its value (Stubs).
Instead of:
configurationMock.Setup(t => t.Folder).Returns("Folder");
configurationMock.Setup(t => t.FileName).Returns("FileName");
you can use
configurationMock.SetupProperty(t => t.Folder, "Folder");
configurationMock.SetupProperty(t => t.FileName, "FileName");
and then access the property as you did:
configurationMock.Object.Folder
More on moq properties can be found here: http://code.google.com/p/moq/wiki/QuickStart#Properties

Moq does It.Is<List<List<string>>>(x => x.Count == 10) do what I think it should do?

I am passing this into the constructor of an object I am unit testing
It.Is<List<List<string>>>(x => x.Count == 10)
but when I step into the constructor, this statement resolves to null instead of a a List<List<string>> with a Count of 10. Am I misunderstanding how this works?
The It.Is method is not meant to be called. Actually, I think it should just throw, instead of returning the default value of the type.
It is meant to be used in the expression trees used to setting expectations:
interface IFoo { bool DoSomething(IList<IList<string>> strings); }
var mock = new Mock<IFoo>();
mock.Setup(f => f.DoSomething(It.Is<IList<IList<string>>>(l => l.Count == 10))
.Returns(true);
The example sets up a mock object of IFoo that will return true when passed an IList<IList<string>> object with 10 elements. This means that after the following call, result will be true:
IList<IList<string>> listWith10Elements = // create a list with 10 elements
bool result = mock.Object.DoSomething(listWith10Elements);
If you're passing something into the constructor of an object, you would normally use the proxy object from a mock, with Setup on that mock providing any context which your class needs.
For instance:
var mock = new Mock<List<List<string>>>();
mock.Setup(x => x.Count()).Returns(10);
var myClass = new MyClass(mock.Object);
Use Verify to check interactions. What you have there is a matcher, which you can use in Setup and Verify to match particular types of arguments.
Except, of course, that you won't be able to mock List because it doesn't have the virtual methods you're after. Try using, and mocking, ICollection<List<string>> instead.
I think this should do what you want. Hope this helps.

Categories

Resources