My generic class takes a Func<T> parameter in constructor, and I want to test one of its methods which basically invoke the constructor parameter.
I use Moq and in my test code is something like this:
[Fact]
public void Construct_EnsureInvokeFunction()
{
_objectToTest=new TypeToTest<T>(It.IsAny<Func<T>>());
_objectToTest.Construct();
//here I want to ensure that the passed parameter is invoked
//however since I can't mock Func<T>, I dont know how to verify
//whether Invoke method of Func<T> is triggered
}
One workaround that I can think is to wrap my Func<T> inside a new interface and create a method to wrap it's Invoke method, and then use Moq to mock the interface. However it doesn't seem effective.
Am I missing something? Any idea will be appreciated.
Thanks,
Anton
You can create a simple fake Func<T> closure with side-effects and verify those side-effects. A good one is incrementing a local variable because it also lets you assert that it was not called more than it should. Something like this:
int counter = 0;
Func<T> f = () => { counter++; return fakeT; }
var objectToTest = new TypeToTest<T>(f);
objectToTest.Construct();
Assert.Equal(1, counter);
You can wrap the Func<T> in an anonymous method that sets a local variable:
bool wasInvoked = false;
Func<T> testFunc = () => { var ret = funcToTest(); wasInvoked = true; return ret; }
// Test something with testFunc instead of funcToTest
...
Assert.IsTrue(wasInvoked);
Related
This is from the factory pattern, where a property is used to get an instance via Create:
public class Dialer
{
public static Func<Dialer> Create;
public bool MakeCall(string number) ...
public Dialer(IDialer impl) { ... }
}
Then a lambda expression is assigned to the property delegate in the platform-specific project with
Dialer.Create = () => new Dialer(new PhoneDialeriOS());
and to get an instance in the platform-independent project I use
this.dialer = Dialer.Create();
Now I'm looking to use
public static Action<Dialer> Create;
If I get this right, the assignment now is
Dialer.Create = (d) => new Dialer(new PhoneDialeriOS());
but how do I get an instance?
this.dialer = // ?
By using this.dialer = Dialer.Create(); I get
Error CS7036 There is no argument given that corresponds to the required formal parameter 'obj' of 'Action'
But it doesn't make sense to pass an instance of PhoneDialeriOS here, because there is no access to it in the platform-independent code. I think the example I'm regarding to is misleading or I'm missing something.
Action<Dialer> is a a delegate that receives a Dialer instance, and returns void. It's an Action, after all. If you want it to return a value (and get an argument), you need to use Func<Dialer, Dialer> instead.
The following could be possible usages
var specific_dialer = new Dialer(new PhoneDialeriOS());
var defualt_dialer = Dialer.Create();
Edit
Of course you can do something like
Dialer.Create = () => new Dialer(new PhoneDialerAndroid());
without the (likely a wrong copy/paste) line with the Action
I have the below class, and I am trying to test the method AddRecordToQueue.
I am using Moq to mock the result of the the AddToQueue method within the AddRecordToQueue method.
The AddToQueue method returns a boolean, so i am trying to mock the result with a true value
public class Test
{
private readonly IRabbitMqConnection rabbitMqConnection;
public Test(IRabbitMqConnection rabbitMqConnection)
{
this.rabbitMqConnection = rabbitMqConnection;
}
public bool AddRecordToQueue(string messageExchange, object data)
{
var jsonified = JsonConvert.SerializeObject(data);
var customerBuffer = Encoding.UTF8.GetBytes(jsonified);
var result = this.rabbitMqConnection.AddToQueue(customerBuffer, messageExchange);
return result;
}
}
My test class looks like the below.
[TestClass]
public class TestCon
{
[TestMethod]
public void MockTest()
{
Moq.Mock<IRabbitMqConnection> rabbitConection = new Moq.Mock<IRabbitMqConnection>();
var draftContactsManager = new Test(rabbitConection.Object);
rabbitConection.Setup(e => e.AddToQueue(null, string.Empty)).Returns((bool res) => true);
var result = draftContactsManager.AddRecordToQueue("someExchange", null);
Assert.IsTrue(result);
}
}
I cant seem to set the moq result as true. Can anyone advise what I am missing
thanks
I think that you need to change the Returns to just return true instead of the lambda. Like this:
rabbitConection.Setup(e => e.AddToQueue(null, string.Empty)).Returns(true)
EDIT:
If this still doesn't work then it is probably due to the parameters not matching. You are passing in "someExchange" but the mock is set up for string.Empty. If you aren't sure what values will be used you could use the It.IsAny method to get around this.
rabbitConection.Setup(e => e.AddToQueue(It.IsAny<byte[]>(), It.IsAny<string>())).Returns(true)
You need to setup the method with the actual arguments it's invoked.
If JsonConvert.SerializeObject(data) returns null, then this is the setup:
rabbitConection.Setup(e => e.AddToQueue(null, "someExchange")).Returns(true)
Additionally, you can setup the method to return true/false regardless of values of the arguments:
rabbitConection.Setup(e => e.AddToQueue(It.IsAny<byte[]>(), It.IsAny<string>())).Returns(true)
With the above setup, the method will return true no matter what what you've passed to the method. The previous example will return true only when the method is called with the setuped arguments.
As the others said, the Setup is incorrect.
You need to call Setup before using the associated Object
It should be something similar to:
...
rabbitConection
.Setup(e => e.AddToQueue(It.IsAny<byte[]>(), It.IsAny<string>()))
.Returns(true);
var draftContactsManager = new Test(rabbitConection.Object);
...
Taken the question from this article (How to moq a Func) and adapted it as the answer is not correct.
public class FooBar
{
private Func<IFooBarProxy> __fooBarProxyFactory;
public FooBar(Func<IFooBarProxy> fooBarProxyFactory)
{
_fooBarProxyFactory = fooBarProxyFactory;
}
public void Process()
{
_fooBarProxyFactory();
_fooBarProxyFactory();
}
}
I have a need to mock a Func<> that is passed as a constructor parameter, the assert that the func was call twice.
When trying to mock the function var funcMock = new Mock<Func<IFooBarProxy>>(); Moq raises and exception as the Func type is not mockable.
The issue is that without mocking the func it is not possible to verify that the func was called (n) times. funcMock.Verify( (), Times.AtLeast(2));
I don't think it is necessary to use a mock for the Func.
You can simply create an ordinary Func yourself that returns a mock of IFooBarProxy:
int numberOfCalls = 0;
Func<IFooBarProxy> func = () => { ++numberOfCalls;
return new Mock<IFooBarProxy>(); };
var sut = new FooBar(func);
sut.Process();
Assert.Equal(2, numberOfCalls);
As of at least Moq 4.5.28, you can mock and verify the Func as you would expect to be able to. I couldn't tell when this feature was added (according to the original question at some point this did not work).
[Test]
public void TestFoobar()
{
var funcMock = new Mock<Func<IFooBarProxy>>();
var fooBar = new FooBar(funcMock.Object);
fooBar.Process();
funcMock.Verify(x => x(), Times.AtLeast(2));
}
Since Moq v4.1.1308.2120
As of this version, which was released some months after this question was asked (Aug 21, 2013), the functionality to mock a Func<> has been added. So with any current version of mock, you can use var funcMock = new Mock<Func<IFooBarProxy>>();.
Original (outdated) answer
If you have a lot of callback Func's, Actions, etc, it's better to define a helper interface in your tests and mock that interface. This way you can use the regular Moq functionality, like setting up return values, testing input arguments, etc.
interface IFooBarTestMethods
{
IFooBarProxy FooBarProxyFactory();
}
Usage
var testMethodsMock = new Mock<IFooBarTestMethods>();
testMethodsMock
.Setup(x => x.FooBarProxyFactory())
.Returns(new Mock<IFooBarProxy>());
var sut = new FooBar(testMethodsMock.Object.FooBarProxyFactory);
testMethodsMock.Verify(x => x.FooBarProxyFactory(), Times.Exactly(2));
For Complex scenario like the below one
public interface ISqlConnector
{
Task<int> ConnectAsync(Func<IDbConnection, Task<int>> performDatabaseOperationAsync, string connectionString);
}
You can use
var funcMock = new Mock<Func<IDbConnection,Task<int>>>();
//setup Mock
sqlConnector.Setup(a => a.ConnectAsync(funcMock.Object, It.IsAny<string>()));
Using Rhino Mocks, how do I ensure that a method is not called while setting up the Expectations on the mock object.
In my example, I am testing the Commit method and I need to ensure that the Rollback method is not called while doing the commit. (this is because i have logic in the commit method that will automatically rollback if commit fails)
Here's how the code looks like..
[Test]
public void TestCommit_DoesNotRollback()
{
//Arrange
var mockStore = MockRepository.GenerateMock<IStore>();
mockStore.Expect(x => x.Commit());
//here i want to set an expectation that x.Rollback() should not be called.
//Act
subject.Commit();
//Assert
mockStore.VerifyAllExpectation();
}
Of course, I can do this at Assert phase like this:
mockStore.AssertWasNotCalled(x => x.Rollback());
But i would like to set this as an Expectation in the first place.
Another option would be:
mockStore.Expect(x => x.Rollback()).Repeat.Never();
Is this what are you looking for?
ITest test = MockRepository.GenerateMock<ITest>();
test.Expect(x => x.TestMethod()).AssertWasNotCalled(mi => {});
Here is another option:
mockStore.Stub(x => x.DoThis()).Repeat.Times(0);
//EXECUTION HERE
x.VerifyAllExpectations();
For this case I created an extension method to better show my intent
public static IMethodOptions<RhinoMocksExtensions.VoidType> ExpectNever<T>(this T mock, Action<T> action) where T : class
{
return mock.Expect(action).IgnoreArguments().Repeat.Never();
}
Note the IgnoreArguments() call. I'm assuming that you don't want the method to be called ever...no matter what the parameter value(s) are.
I have this interface that returns void in some functions that I would like to mock and wonder what is the correct way of doing so. As of now I have the following:
var mocks = new MockRepository();
var mockedInterface = mocks.CreateMock<IMyInterface>();
Expect.Call(mockedInterface.FunctionThatReturn(param1, param2)).Return(Something);
mockedInterface.FunctionReturningVoid(param3, param4);
mocks.ReplayAll();
// Some assert and other stuff
mocks.VerifyAll();
Is that the right way of doing it? I think it looks weird since you're not handling the two functions the same way. What I would like to write is:
var mocks = new MockRepository();
var mockedInterface = mocks.CreateMock<IMyInterface>();
Expect.Call(mockedInterface.FunctionThatReturn(param1, param2)).Return(Something);
Expect.Call(mockedInterface.FunctionReturningVoid(param3, param4)); // This doesn't work.
mocks.ReplayAll();
// Some assert and other stuff
mocks.VerifyAll();
But that doesn't work on row 4. I found some blog that says you can use lambdas (or delegate) like
Expect.Call(() => mockedInterface.FunctionReturningVoid(param3, param4)); // This doesn't work.
But that doesn't seem to work either for me. Having the Expect.Call makes it easy to identify mocked functions and that is why I want it. The compile error I get is: "Cannot convert lambda expression to type 'object' because it is not a delegate type".
So how should it be done?
UPDATE: Added compile error information.
I prefer the AAA (arrange/act/assert) syntax instead of record/replay. It's more straightforward and makes the tests easier to read. What you'll want to do is:
// arrange
var mock = MockRepository.GenerateMock<IMyInterface>
mock.Expect(i => i.FunctionThatReturnSomething(param1, param2)).Return("hello");
mock.Expect(i => i.FunctionThatReturnVoid(param3, param4));
// set up other stuff for your code (like whatever code depends on IMyInterface)
var foo = new Foo(mock);
// act
foo.DoSomething();
// assert
mock.VerifyAll();
For void methods I use anonymous delegates:
Expect.Call(delegate { mockedInterface.FunctionReturningVoid(param3, param4); })
BTW: I like Record-Playback syntax for replaying and verifying expectations
http://www.ayende.com/Wiki/(S(j2mgwqzgkqghrs55wp2cwi45))/Comparison+of+different+Rhino+Mocks+syntaxes.ashx
Not sure how to test void method in AAA pattern, I was also having trouble mocking void. However, in the past, I use the Record and Playback style, and that should work.
Example:
private MockRepository m_mocks = new MockRepository();
private IXGateManager xGateManager = m_mocks.DynamicMock<IXGateManager>();
using (m_mocks.Record())
{
xGateManager.SendXGateMessage(null, null);
LastCall.IgnoreArguments().Repeat.Once();
}
using (m_mocks.Playback())
{
//... execute your test
}