Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different return values the first and second time with Moq

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?

like image 714
marcus Avatar asked Sep 02 '11 18:09

marcus


People also ask

What is Moq callback?

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.

What is verifiable in Moq?

Verifiable is to enlist a Setup into a set of "deferred Verify(...) calls" which can then be triggered via mock. Verify() .

How do you set a mock object property?

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.

What does Moq setup do?

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.


2 Answers

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); 
like image 94
stackunderflow Avatar answered Sep 22 '22 12:09

stackunderflow


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); 
like image 31
mo. Avatar answered Sep 19 '22 12:09

mo.