In nUnit 3, there's been considerable changes made, among which the ExpectedException has been dropped to be replaced by the assertion model.
I've found this and this example but the recommendation is to use Assert.That() instead so I want to use this approach as shown below.
//Arrange
string data = "abcd";
//Act
ActualValueDelegate<object> test = () => data.MethodCall();
//Assert
Assert.That(test, Throws.TypeOf<ExceptionalException>());
However, I'd like to test the assert for a number of different parameters but I can't seem to get it to work. I've tried the following.
List<List<Stuff>> sets = new[] { 0, 1, 2 }
.Select(_ => Enumerable.Repeat(new Stuff(_), _).ToList())
.ToList();
Assert.Throws(() => Transform.ToThings(new List<Stuff>()));
The above works as to creating the list of lists, as desired and testing the Transform.Stuff() call. However, I haven't figured out a way to plug sets into things.
Is it possible? Where are the examples? (Most of the searches drown in nUnit 2.x and on the official documentation site, I see nothing that helps me.)
You should look into using the TestCaseSource attribute to define the inputs to your method:
[TestCaseSource("StuffSets")]
public void ToThings_Always_ThrowsAnException(List<Stuff> set)
{
// Arrange
// Whatever you need to do here...
// Act
ActualValueDelegate<object> test = () => Transform.ToThings(set);
// Assert
Assert.That(test, Throws.TypeOf<SomeKindOfException>());
}
public static IEnumerable<List<Stuff>> StuffSets =
{
get
{
return new[] { 0, 1, 2 }
.Select(_ => Enumerable.Repeat(new Stuff(_), _).ToList())
.ToList();
}
};
This will invoke ToThings_Always_ThrowsAnException once for each List<Stuff> that is returned from StuffSets (here, three times).
Update 1, more details
My question was hard to interpret, sorry for that....
Simple question...
How do you test a specific implementation with Moq?
interface IShipping
{
int CalculateCost();
}
class TruckShipping: IShipping
{
int CalculateCost()
{
return 9;
}
}
class Shipping: IShipping
{
int CalculateCost()
{
return 5;
}
}
class CalculateSomethingMore
{
IShipping _shipping;
CalculateSomethingMore(IShipping shipping)
{
// Here I want the TruckShipping implementation!
_shipping = shipping;
}
DoCalc()
{
return _shipping.CalculateCost * 2;
}
}
Without mock it would probably look like (if you don't use DI)
TEST:
var truckShipping = new TruckShipping();
var advancedCalculation = CalculateSomethingMore(truckShipping);
var result = DoCalc();
var expected = 18;
Assert.IsTrue(result == expected);
NUnit, FluentAssertions, MbUnit, xUnit, etc.. doesn't matter :)
Test:
var truckShipping = Mock.Of<IShipping> .... ? I want to test the TruckShipping implementation.
and inject that into CalculateSomethingMore.
If you want to test TruckShipping implementation then you need separate tests for TruckShipping implementation.
Currently you are testing behavior of CalculateSomethingMore, which should return doubled value of cost, calculated by shipping. You don't care which shipping. Responsibility of CalculateSomethingMore is asking shipping about it's cost, and doubling that cost:
Mock<IShipping> shipping = new Mock<IShipping>();
shipping.Setup(s => s.CalculateCost()).Returns(10);
CalculateSomethingMore sut = new CalculateSomethingMore(shipping.Object);
Assert.That(20, Is.EqualTo(sut.DoCalc()));
shipping.VerifyAll();
You can see, that this test uses neither 9 nor 5 as shipping cost. Why? Because you actually don't care what value it will have. Calculating shipping cost is not responsibility of class under test.
Also you need another test for your TruckShipping implementation, which will verify, that TruckShipping calculates shipping cost correctly (this is a responsibility of your shipping object):
TruckShipping sut = new TruckShipping();
Assert.That(9, Is.EqualTo(sut.DoCalc());
Moq is not a testing framework, it's a mockinq framework, so it does not provide testing features.
For testing you can use SharpTestEx, for example you can write:
[TestMethod]
public void VerifyCostIsCorrect()
{
new TruckShipping()
.CalculateCost()
.Should("The TruckShipping implementation returns a wrong cost.").Be.EqualTo(9);
}
You use mocks to replace real dependencies (which often are too complex to instantiate) with faked, lightweight objects. Testing mocked object makes no sense at all because essentially, you'll be testing auto-generated code from some 3rd party library.
Edit:
It's still unclear why would you want to depend on concrete implementation, especially considering you're using IoC and inject IShipping. Anyways, I think you want something that can simulate TruckShipping, but not TruckShipping itself. If so, it's simple:
var shippingMock = new Mock<IShipping>();
// setting up mock to return 9 makes it behave as if it was TruckShipping
shippingMock.Stub(s => s.CalculateCost()).Returns(9);
var advancedCalculation = CalculateSomethingMore(shippingMock.Object);
var result = DoCalc();
var expected = 18;
Assert.IsTrue(result == expected);
I need to test the following method:
CreateOutput(IWriter writer)
{
writer.Write(type);
writer.Write(id);
writer.Write(sender);
// many more Write()s...
}
I've created a Moq'd IWriter and I want to ensure that the Write() methods are called in the right order.
I have the following test code:
var mockWriter = new Mock<IWriter>(MockBehavior.Strict);
var sequence = new MockSequence();
mockWriter.InSequence(sequence).Setup(x => x.Write(expectedType));
mockWriter.InSequence(sequence).Setup(x => x.Write(expectedId));
mockWriter.InSequence(sequence).Setup(x => x.Write(expectedSender));
However, the second call to Write() in CreateOutput() (to write the id value) throws a MockException with the message "IWriter.Write() invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.".
I'm also finding it hard to find any definitive, up-to-date documentation/examples of Moq sequences.
Am I doing something wrong, or can I not set up a sequence using the same method?
If not, is there an alternative I can use (preferably using Moq/NUnit)?
There is bug when using MockSequence on same mock. It definitely will be fixed in later releases of Moq library (you can also fix it manually by changing Moq.MethodCall.Matches implementation).
If you want to use Moq only, then you can verify method call order via callbacks:
int callOrder = 0;
writerMock.Setup(x => x.Write(expectedType)).Callback(() => Assert.That(callOrder++, Is.EqualTo(0)));
writerMock.Setup(x => x.Write(expectedId)).Callback(() => Assert.That(callOrder++, Is.EqualTo(1)));
writerMock.Setup(x => x.Write(expectedSender)).Callback(() => Assert.That(callOrder++, Is.EqualTo(2)));
I've managed to get the behaviour I want, but it requires downloading a 3rd-party library from http://dpwhelan.com/blog/software-development/moq-sequences/
The sequence can then be tested using the following:
var mockWriter = new Mock<IWriter>(MockBehavior.Strict);
using (Sequence.Create())
{
mockWriter.Setup(x => x.Write(expectedType)).InSequence();
mockWriter.Setup(x => x.Write(expectedId)).InSequence();
mockWriter.Setup(x => x.Write(expectedSender)).InSequence();
}
I've added this as an answer partly to help document this solution, but I'm still interested in whether something similar could be achieved using Moq 4.0 alone.
I'm not sure if Moq is still in development, but fixing the problem with the MockSequence, or including the moq-sequences extension in Moq would be good to see.
I wrote an extension method that will assert based on order of invocation.
public static class MockExtensions
{
public static void ExpectsInOrder<T>(this Mock<T> mock, params Expression<Action<T>>[] expressions) where T : class
{
// All closures have the same instance of sharedCallCount
var sharedCallCount = 0;
for (var i = 0; i < expressions.Length; i++)
{
// Each closure has it's own instance of expectedCallCount
var expectedCallCount = i;
mock.Setup(expressions[i]).Callback(
() =>
{
Assert.AreEqual(expectedCallCount, sharedCallCount);
sharedCallCount++;
});
}
}
}
It works by taking advantage of the way that closures work with respect to scoped variables. Since there is only one declaration for sharedCallCount, all of the closures will have a reference to the same variable. With expectedCallCount, a new instance is instantiated each iteration of the loop (as opposed to simply using i in the closure). This way, each closure has a copy of i scoped only to itself to compare with the sharedCallCount when the expressions are invoked.
Here's a small unit test for the extension. Note that this method is called in your setup section, not your assertion section.
[TestFixture]
public class MockExtensionsTest
{
[TestCase]
{
// Setup
var mock = new Mock<IAmAnInterface>();
mock.ExpectsInOrder(
x => x.MyMethod("1"),
x => x.MyMethod("2"));
// Fake the object being called in order
mock.Object.MyMethod("1");
mock.Object.MyMethod("2");
}
[TestCase]
{
// Setup
var mock = new Mock<IAmAnInterface>();
mock.ExpectsInOrder(
x => x.MyMethod("1"),
x => x.MyMethod("2"));
// Fake the object being called out of order
Assert.Throws<AssertionException>(() => mock.Object.MyMethod("2"));
}
}
public interface IAmAnInterface
{
void MyMethod(string param);
}
The simplest solution would be using a Queue:
var expectedParameters = new Queue<string>(new[]{expectedType,expectedId,expectedSender});
mockWriter.Setup(x => x.Write(expectedType))
.Callback((string s) => Assert.AreEqual(expectedParameters.Dequeue(), s));
Recently, I put together two features for Moq: VerifyInSequence() and VerifyNotInSequence(). They work even with Loose Mocks. However, these are only available in a moq repository fork:
https://github.com/grzesiek-galezowski/moq4
and await more comments and testing before deciding on whether they can be included in official moq releaase. However, nothing prevents you from downloading the source as ZIP, building it into a dll and giving it a try. Using these features, the sequence verification you need could be written as such:
var mockWriter = new Mock<IWriter>() { CallSequence = new LooseSequence() };
//perform the necessary calls
mockWriter.VerifyInSequence(x => x.Write(expectedType));
mockWriter.VerifyInSequence(x => x.Write(expectedId));
mockWriter.VerifyInSequence(x => x.Write(expectedSender));
(note that you can use two other sequences, depending on your needs. Loose sequence will allow any calls between the ones you want to verify. StrictSequence will not allow this and StrictAnytimeSequence is like StrictSequence (no method calls between verified calls), but allows the sequence to be preceeded by any number of arbitrary calls.
If you decide to give this experimental feature a try, please comment with your thoughts on:
https://github.com/Moq/moq4/issues/21
Thanks!
I've just had a similar scenario, and inspired by the accepted answer, I've used the following approach:
//arrange
var someServiceToTest = new SomeService();
var expectedCallOrder = new List<string>
{
"WriteA",
"WriteB",
"WriteC"
};
var actualCallOrder = new List<string>();
var mockWriter = new Mock<IWriter>();
mockWriter.Setup(x => x.Write("A")).Callback(() => { actualCallOrder.Add("WriteA"); });
mockWriter.Setup(x => x.Write("B")).Callback(() => { actualCallOrder.Add("WriteB"); });
mockWriter.Setup(x => x.Write("C")).Callback(() => { actualCallOrder.Add("WriteC"); });
//act
someServiceToTest.CreateOutput(_mockWriter.Object);
//assert
Assert.AreEqual(expectedCallOrder, actualCallOrder);
Moq has a little-known feature called Capture.In, which can capture arguments passed to a method. With it, you can verify call order like this:
var calls = new List<string>();
var mockWriter = new Mock<IWriter>();
mockWriter.Setup(x => x.Write(Capture.In(calls)));
CollectionAssert.AreEqual(calls, expectedCalls);
If you have overloads with different types, you can run the same setup for overloads too.
My scenario was methods without parameters:
public interface IWriter
{
void WriteA ();
void WriteB ();
void WriteC ();
}
So I used Invocations property on the Mock to compare what was called:
var writer = new Mock<IWriter> ();
new SUT (writer.Object).Run ();
Assert.Equal (
writer.Invocations.Select (invocation => invocation.Method.Name),
new[]
{
nameof (IWriter.WriteB),
nameof (IWriter.WriteA),
nameof (IWriter.WriteC),
});
You could also append the invocation.Arguments to check method calls with parameters.
Also the failure message is more clear than just expected 1 but was 5:
expected
["WriteB", "WriteA", "WriteC"]
but was
["WriteA", "WriteB"]
I suspect that expectedId is not what you expect.
However i'd probably just write my own implementation of IWriter to verify in this case ... probably a lot easier (and easier to change later).
Sorry for no Moq advice directly. I love it, but haven't done this in it.
do you maybe need to add .Verify() at the end of each setup? (That really is a guess though i'm afraid).
I am late to this party but I wanted to share a solution that worked for me since it seems as though all of the referenced solutions did not work with verifying the same method call (with the same arguments) multiple times in order. In addition the referenced bug, Moq Issue #478 was closed without a solution.
The solution presented utilizes the MockObject.Invocations list to determine order and sameness.
public static void VerifyInvocations<T>(this Mock<T> mock, params Expression<Action<T>>[] expressions) where T : class
{
Assert.AreEqual(mock.Invocations.Count, expressions.Length,
$"Number of invocations did not match expected expressions! Actual invocations: {Environment.NewLine}" +
$"{string.Join(Environment.NewLine, mock.Invocations.Select(i => i.Method.Name))}");
for (int c = 0; c < mock.Invocations.Count; c++)
{
IInvocation expected = mock.Invocations[c];
MethodCallExpression actual = expressions[c].Body as MethodCallExpression;
// Verify that the same methods were invoked
Assert.AreEqual(expected.Method, actual.Method, $"Did not invoke the expected method at call {c + 1}!");
// Verify that the method was invoked with the correct arguments
CollectionAssert.AreEqual(expected.Arguments.ToList(),
actual.Arguments
.Select(arg =>
{
// Expressions treat the Argument property as an Expression, do this to invoke the getter and get the actual value.
UnaryExpression objectMember = Expression.Convert(arg, typeof(object));
Expression<Func<object>> getterLambda = Expression.Lambda<Func<object>>(objectMember);
Func<object> objectValueGetter = getterLambda.Compile();
return objectValueGetter();
})
.ToList(),
$"Did not invoke step {c + 1} method '{expected.Method.Name}' with the correct arguments! ");
}
}
I am creating a mock for my ITransformer interface.
public interface ITransformer
{
String Transform( String input );
}
I can create a mock that returns an given string based on a specific input:
var mock = new Mock<ITransformer>();
mock.Setup(s => s.Transform("foo")).Returns("bar");
What I would like to do is create a mock with a Transform() method that echoes whatever is passed to it. How would I go about doing this? Is it even possible?
I realise my question might be subverting the way that Moq and mocks in general are supposed to work because I'm not specifying a fixed expectation.
I also know that I could easily create my own class to do this, but I was hoping to find a generic approach that I could use in similar circumstances without having to define a new class each time.
var mock = new Mock<ITransformer>();
m.Setup(i => i.Transform(It.IsAny<string>())).Returns<string>((string s) => { return s;});
var mock = new Mock<ITransformer>();
mock.Setup(t => t.Transform(It.IsAny<string>())).Returns((String s) => s);
This should echo back whatever was supplied to the method.
I'm trying to mock the Add method of subsonic SimpleRepository with Rihino mocks, I'm using the IRepository Interface but I'm new to mocking and dont know how to go from there, can this be done? thanks for your help.
AdamRalph is correct, but I prefer the AAA syntax of Rhino Mocks:
// arrange
var repo = MockRepository.GenerateStub<IRepository>();
var myObject = CreateSampleObject();
repo.Stub(r => r.Add(myObj)).Return(myObj);
// act (this assumes that the call to "SomeMethod" on "SomeClass"
// returns the result of the IRepository.Add).
var someClass = new SomeClass(repo);
var result = someClass.SomeMethod();
// assert
Assert.AreSame(myObject, result);
It depends what you want to test. Do you care if the Add() method is called or not, or do you just want to set up a canned response which may or may not be called?
If you expect the call:-
var mocks = new MockRepository();
var repo = mocks.StrictMock<IRepository>():
var myObj = CreateSampleObject();
using(mocks.Record())
{
Expect.Call(repo.Add(myObj)).Return(myObj);
}
using(mocks.Playback())
{
var target = CreateTarget(repo);
target.DoSomething(myObj);
}
If you don't care whether it is called or not, then use SetUpResult instead of Expect, e.g.
SetUpResult.For(rep.Add(myObj)).Return(myObj);