I have a test like this:
[TestCase("~/page/myaction")] public void Page_With_Custom_Action(string path) { // Arrange var pathData = new Mock<IPathData>(); var pageModel = new Mock<IPageModel>(); var repository = new Mock<IPageRepository>(); var mapper = new Mock<IControllerMapper>(); var container = new Mock<IContainer>(); container.Setup(x => x.GetInstance<IPageRepository>()).Returns(repository.Object); repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(() => pageModel.Object); pathData.Setup(x => x.Action).Returns("myaction"); pathData.Setup(x => x.Controller).Returns("page"); var resolver = new DashboardPathResolver(pathData.Object, repository.Object, mapper.Object, container.Object); // Act var data = resolver.ResolvePath(path); // Assert Assert.NotNull(data); Assert.AreEqual("myaction", data.Action); Assert.AreEqual("page", data.Controller); }
GetPageByUrl
runs twice in my DashboardPathResolver
, how can I tell Moq to return null
the first time and pageModel.Object
the second?
Callbacks. A powerful capability of Moq is to attach custom code to configured methods and properties' getters and setters. This capability is often referred to as Callbacks.
Verifiable is to enlist a Setup into a set of "deferred Verify(...) calls" which can then be triggered via mock. Verify() .
You can set the mock object property to the value returned by the mock object method. To achieve this, specify separate behaviors for the method and the property. You can specify one behavior at a time. For more information about mock object behavior, see Specify Mock Object Behavior.
Moq provides a library that makes it simple to set up, test, and verify mocks. We can start by creating an instance of the class we're testing, along with a mock of an interface we want to use.
With the latest version of Moq(4.2.1312.1622), you can setup a sequence of events using SetupSequence. Here's an example:
_mockClient.SetupSequence(m => m.Connect(It.IsAny<String>(), It.IsAny<int>(), It.IsAny<int>())) .Throws(new SocketException()) .Throws(new SocketException()) .Returns(true) .Throws(new SocketException()) .Returns(true);
Calling connect will only be successful on the third and fifth attempt otherwise an exception will be thrown.
So for your example it would just be something like:
repository.SetupSequence(x => x.GetPageByUrl<IPageModel>(virtualUrl)) .Returns(null) .Returns(pageModel.Object);
The existing answers are great, but I thought I'd throw in my alternative which just uses System.Collections.Generic.Queue
and doesn't require any special knowledge of the mocking framework - since I didn't have any when I wrote it! :)
var pageModel = new Mock<IPageModel>(); IPageModel pageModelNull = null; var pageModels = new Queue<IPageModel>(); pageModels.Enqueue(pageModelNull); pageModels.Enqueue(pageModel.Object);
Then...
repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(pageModels.Dequeue);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With