I try to use the SetupSequence method of the Moq 4.5 framework.
Class that should be mocked:
public class OutputManager {
public virtual string WriteMessage(string message) {
// write a message
}
}
Mock:
var outputManagerMock = new Mock<OutputManager>();
var writeMessageCalls = 0;
var currentMessage = String.Empty;
outputManagerMock.Setup(o => o.WriteMessage(It.IsAny<string>())).Callback((string m) => {
writeMessageCalls++;
message = m;
});
This code works fine. But I'd like having a different setup for each call of the WriteMessage method. Well, I use SetupSequence instead of Setup:
var outputManagerMock = new Mock<OutputManager>();
var writeMessageCalls = 0;
var firstMessage = String.Empty;
var secondMessage = String.Empty;
outputManagerMock.SetupSequence(o => o.WriteMessage(It.IsAny<string>()))
.Callback((string m) => {
writeMessageCalls++;
firstMessage = m;
}).Callback((string m) => {
writeMessageCalls++;
secondMessage = m;
});
Then I've got the error:
Error CS0411 The type arguments for method
'SequenceExtensions.SetupSequence<TMock, TResult>(Mock<TMock>,
Expression<Func<TMock, TResult>>)' cannot be inferred from the usage.
Try specifying the type arguments explicitly.
I've found the possible solution here - SetupSequence in Moq. But it looks like a workaround.
SetupSequence is used to setup a sequence of returns based on the number of the attempt to use the method that is being set up. An example based on your code which demonstrates what I am talking about :
outputManagerMock.SetupSequence(o => o.WriteMessage(It.IsAny<string>()))
.Returns("Hello for the first attempt!")
.Returns("This is the second attempt to access me!")
.Throws(new Exception());
If OutputManager is a dependency for other classes then you should consider abstracting that class to make it easier to mock for your tests.
public interface IOutputManager {
string WriteMessage(string message);
}
That would then mean that the implementation of this interface would look like what you had originally with the addition of the interface.
public class OutputManager : IOutputManager {
public string WriteMessage(string message) {
// write a message
}
}
Given that you originally attempted to mock OutputManager then the assumption here is that it is not the system under test as you typically do not mock the target of the test but rather its dependencies.
So let's assume a dependent class looked something like this.
public class DependentOnIOutputManager {
private IOutputManager outputManager;
public DependentOnIOutputManager(IOutputManager outputManager) {
this.outputManager = outputManager;
}
public string SomeMethod(string message) {
// write a message
var output = outputManager.WriteMessage(message);
//...other code
return output;
}
}
Then an example test could look like this.
[TestMethod]
public void Moq_SetupSequence_Example() {
//Arrange
var mock = new Mock<IOutputManager>();
mock.SetupSequence(x => x.WriteMessage(It.IsAny<string>()))
.Returns("first")
.Returns("second")
.Throws<InvalidOperationException>();
var outputManager = mock.Object;
var sut = new DependentOnIOutputManager(outputManager);
//Act
var first = sut.SomeMethod("1st");
var second = sut.SomeMethod("2nd");
Exception e = null;
try {
sut.SomeMethod("3rd");
} catch (InvalidOperationException ex) {
e = ex;
}
//Assert
Assert.IsNotNull(first);
Assert.IsNotNull(second);
Assert.IsNotNull(e);
}
Related
I want to ask the best way how to mock static a method in an another class. I know that mock is not working for a static class. Here is my Code so far. I don't want to call SearchSomething() at the time because it's external interaction
public ResponseBase GetData(string searchId)
{
try
{
var request = new SearchRequest
{
SearchId = searchId
};
var response = SearchLogic.SearchSomething(request);
return response;
}
catch (Exception e)
{
return ResponseBase.ExceptionHandling(e);
}
}
public class SearchLogic(){
public static ResponseBase SearchSomething(SearchRequest request)
{
//Do Something
return new ResponseBase;
}
}
This is my UnitClass
[TestClass]
public class UnitClass
{
[TestMethod]
public void PositiveSearchTest()
{
//arrange
string searchId = "name";
var expected = new SearchRequest();
SearchtController search = new SearchtController();
var staticMock = new Mock<SearchLogic>();
staticMock.Setup(s => s.SearchSomething()).Returns(new ResponseBase());
//act
var actual = search.GetData(searchId);
//assert
Assert.AreEqual(actual, expected);
}
}
While this question gives one way to solve this, my preferred solution would be different: modify SearchLogic so it is no longer static. After that, you can then mock it to your heart's content. Static methods are always a complete pain for unit testing; I try to use them only for situations where there is one and only one correct behaviour.
This obviously assumes you have the ability to modify SearchLogic. If you don't, see the linked question.
I'm trying to do a simple test, mocking the sum method.
I have an interface:
public interface ISumSomething
{
int Sum(params int[] values);
}
A class that use this interface:
public class CallSum
{
public CallSum(ISumSomething sumSomething)
{
this.SumSomething = sumSomething;
}
private ISumSomething SumSomething { get; set; }
public int Execute(params int[] values)
{
return this.SumSomething.Sum(values);
}
}
And the test class:
[TestMethod]
public void Test_Sum_Method()
{
// Creates MOQ.
var instance = new Mock<ISumSomething>();
// Setup de MOQ.
instance.Setup(moq => moq.Sum(It.IsAny(1,2)).Returns(4));
// Instance the object.
var sum = new CallSum(instance.Object);
// Execute the operation.
var result = sum.Execute(2, 2);
// Check the result.
Assert.AreEqual(4, result);
}
The problem is, when I call the Execute method, it is returing 0, but in my MOQ, I'm setting 4. Why this happens?
In your Setup you say IsAny(1,2), those arguments don't match the arguments on Execute which are 2,2
You should instead be using:
instance.Setup(moq => moq.Sum(It.IsAny<int[]>()).Returns(4));
(See Setup Method With Params Array for more info)
I have an interface:
public interface IRepeater
{
void Each(string path, Action<string> action);
}
I want to mock this interface using Moq. Now I can obviously do the following:
var mock = new Mock<IRepeater>();
mock.Setup(m => m.Each(It.IsAny<string>(), It.IsAny<Action<string>>());
However, to aid testing I want to be able to mock the string that gets passed to the Action<string>. Can this be done with Moq? If yes, how?
Update
To clarify I am testing a different class that has a dependency on IRepeater. I want to mock IRepeater.Each so I can control the string that the Action gets so I can test the behaviour.
Example
So if I have a class like so.
public class Service
{
private readonly IRepeater _repeater;
public Service(IRepeater repeater)
{
_repeater = repeater;
}
public string Parse(string path)
{
var builder = new StringBuilder();
_repeater.Each(path, line => builder.Append(line));
return builder.ToString();
}
}
How do I mock IRepeater.Each so that I can test Service.Parse?
You have to use callback method. Since line => builder.Append(line) is part of the method behavior, you have to execute this behavior when you test the method:
[TestMethod]
public void Test_Service_When_Passing_String_And_ActionDelegate()
{
var fakeReporter = new Mock<IRepeater>();
fakeReporter.Setup(x => x.Each(It.IsAny<string>(), It.IsAny<Action<string>>()))
.Callback<string, Action<string>>((s, action) => action(s));
var target = new Service(fakeReporter.Object);
var result = target.Parse("asdfghj");
Assert.AreEqual("asdfghj", result);
}
Another approach to test this method is to verify the method was called with the correct path and then verify that the action is the correct action:
[TestMethod]
public void Test_Service_When_Passing_String_And_ActionDelegate()
{
var fakeReporter = new Mock<IRepeater>();
fakeReporter.Setup(x => x.Each(It.IsAny<string>(), It.IsAny<Action<string>>()))
.Callback<string, Action<string>>((s, action) =>
{
Assert.AreEqual("asdfghj", s);
foreach (var w in "pass")
{
action(w.ToString());
}
});
var target = new Service(fakeReporter.Object);
var result = target.Parse("asdfghj");
Assert.AreEqual("pass", result);
}
BTW you can replace the It.IsAny<string>() with the string and then remove the Assert.AreEqual("asdfghj", s);(I just like to test things in the explicit way...)
Seems like you are looking to verify that a passed Action (delegate) will be passed to the IRepeater Call. Because you are not testing the Repeater but a Repeater caller (The Repeater is the mock and not the tested subject).
Here is how I would have done it:
public class Service
{
private readonly IRepeater repeater;
public Service(IRepeater repeater)
{
this.repeater = repeater;
}
public void Foo(string str, Action<string> action)
{
repeater.Each(str, action);
}
}
public class ActionImplement
{
public virtual void Action(string str)
{
Console.Write(str);
}
}
public interface IRepeater
{
void Each(string path, Action<string> action);
}
And the test would have verify the passing of ActionImplement.Action
[TestMethod]
public void Test_Service_When_Passing_String_And_ActionDelegate()
{
var actionImplement = new Mock<ActionImplement>();
actionImplement.Setup(m => m.Action(It.IsAny<string>()));
var mock = new Mock<IRepeater>();
mock.Setup(m => m.Each(It.IsAny<string>(), actionImplement.Object.Action));
var srv = new Service(mock.Object);
srv.Foo("aa",actionImplement.Object.Action);
mock.Verify(ai => ai.Each("aa", actionImplement.Object.Action));
}
Anyone have any idea why below still calls YesService?
It almost seems like IYesService is considered separate to YesService..
Any ideas?
public interface IYesService
{
string Hello();
}
public class YesService : IYesService
{
public string Hello()
{
return "Yes";
}
}
class Program
{
static void Main(string[] args)
{
var _mock = new Mock<IYesService>();
_mock.Setup(x => x.Hello()).Returns("No");
var service = new YesService();
var result = service.Hello();
Console.Write(result);
Console.ReadLine();
}
}
Because you don't use the _mock, you instantiate the YesService and call the method on that.
You can use mocking when you consume this interface:
public class ServiceUser
{
private IYesService _yesService;
public ServiceUser(IYesService yesService)
{
_yesService = yesService;
}
public string CallService()
{
return _yesService.Hello();
}
}
Then use it like this:
var serviceMock = new Mock<IYesService>();
serviceMock.Setup(x => x.Hello()).Returns("No");
var service = new ServiceUser(serviceMock.Object);
var result = service.CallService();
You are creating an instance of YesService (the concrete class) in your Main method. The var service line an be done away with, and the var result line should become:
var result = _mock.Object.Hello();
Try that...
I've have searched on this and it seems to be a catch all, unfortunately everything I've read doesn't help figure it out. Here is the class:
public interface IMockInterface
{
MockClass MockedMethod();
MockClass MockThis();
}
public class MockClass : IMockInterface
{
public virtual MockClass MockedMethod()
{
MockClass returnValue;
returnValue = new MockClass();
returnValue.SomeMessage = "Not mocked";
return returnValue;
}
public MockClass MockThis()
{
MockClass mock;
MockClass returnValue;
mock = new MockClass();
return mock.MockedMethod();
}
}
And the test:
public void MockTest_Internal()
{
MockClass mainClass;
MockClass returnedClass;
IMockInterface mockProvider;
mainClass = new MockClass();
mockProvider = repository.StrictMock<IMockInterface>();
Expect.Call(mockProvider.MockedMethod())
.Return(new MockClass { SomeMessage = "Mocked" });
repository.ReplayAll();
returnedClass = mainClass.MockThis();
provider.AssertWasCalled(item => item.MockedMethod());
Assert.IsTrue(returnedClass.SomeMessage == "Mocked");
}
And have also tried and doesn't work
But I keep getting this exception:
Rhino.Mocks.Exceptions.ExpectationViolationException:
IMockInterface.MockedMethod(); Expected #1, Actual #0
Now from what I've read this would suggest either the method was called with different than expected parameters OR the method was never called but was expected to be called. This isn't the case for the test.
Side Note: This is my first time really using Rhino.Mocks without some in house code so I am basically picking it up as I go. There could be something really stupid here...
This was the old test commented on, but is not what I should have been using:
public void MockTest_Internal()
{
MockClass mainClass;
MockClass returnedClass;
IMockInterface mockProvider;
mainClass = new MockClass();
var provider = MockRepository.GenerateStub<IMockInterface>();
provider.Stub(item => item.MockedMethod())
.Return(new MockClass { SomeMessage = "Mocked" });
returnedClass = mainClass.MockThis();
provider.AssertWasCalled(item => item.MockedMethod());
Assert.IsTrue(returnedClass.SomeMessage == "Mocked");
}
You're telling the mock framework to stub the MockedMethod class on the provider object, but you never inject the provider into the mainClass object to be used. It's not clear to me what you are trying to accomplish but if you want the mocked method to be called then it has to be called on the object on which the stub was set up.
If you define MockThis as below, I think you will find that it will work.
public MockClass MockThis(IMockInterface provider)
{
return provider.MockMethod();
}
The bottom line is that you get the exception because the method was never called on the provider, only on the mainClass object.
EDIT: Example
public class ClassUnderTest
{
private ProviderClass provider { get; set; }
public ClassUnderTest( ProviderClass provider )
{
this.Provider = provider;
}
public int DoOperation()
{
return this.Provider.ProviderOperation();
}
}
public class ProviderClass
{
private int value = 42;
public ProviderClass()
{
}
public virtual int ProviderOperation()
{
return this.value;
}
}
[TestMethod]
public void DoOperationTest()
{
ProviderClass mockProvider = MockRepository.GenerateMock<ProviderClass>();
mockProvider.Expect( mp => mp.ProviderOperation() ).Return( -1 );
ClassUnderTest target = new ClassUnderTest( mockProvider );
int expectedValue = -1;
int value = target.DoOperation();
Assert.AreEqual( expectedValue, value );
mockProvider.VerifyAllExpectations();
}
Normally the ProviderClass object would return 42 from the ProviderOperation method, but we've mocked it out and told it to return -1. When the ClassUnderTest DoOperation method is called, the mock provider object's ProviderOperation method is invoked and returns the mocked value of -1.
Hope this helps.
I usually get this error when a stubbed method is called with an object argument that I build in the test and in the tested code the object is built before calling that method. The solution is to use the Rhino.Mocks Matches().
Ex:
Arg<string>.Matches(s => s.Contains("some substring"))