valores tipos retornan que parametros metodos funciones ejemplos consola con c# unit-testing nunit moq

c# - retornan - tipos de funciones en c



Diferentes valores de retorno la primera y la segunda vez con Moq (7)

Agregar una devolución de llamada no me funcionaba, usé este método en su lugar http://haacked.com/archive/2009/09/29/moq-sequences.aspx y terminé con una prueba como esta:

[TestCase("~/page/myaction")] [TestCase("~/page/myaction/")] public void Page_With_Custom_Action(string virtualUrl) { // 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>(virtualUrl)).ReturnsInOrder(null, 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(virtualUrl); // Assert Assert.NotNull(data); Assert.AreEqual("myaction", data.Action); Assert.AreEqual("page", data.Controller); }

Tengo una prueba como esta:

[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 se ejecuta dos veces en mi dashboardpathresolver, ¿cómo puedo decirle a Moq que devuelva null la primera vez y pageModel.Ojbect el segundo?



Con la última versión de Moq (4.2.1312.1622), puede configurar una secuencia de eventos usando SetupSequence . Aquí hay un ejemplo:

_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);

Llamar a connect solo tendrá éxito en el tercer y quinto intento; de lo contrario, se lanzará una excepción.

Entonces, para su ejemplo, sería algo así como:

repository.SetupSequence(x => x.GetPageByUrl<IPageModel>(virtualUrl)) .Returns(null) .Returns(pageModel.Object);


La respuesta aceptada , así como la respuesta de SetupSequence , maneja las constantes de retorno.

Returns() tiene algunas sobrecargas útiles en las que puede devolver un valor basado en los parámetros que se enviaron al método simulado. De acuerdo con http://haacked.com/archive/2009/09/29/moq-sequences.aspx dada en la respuesta aceptada, aquí hay otro método de extensión para esas sobrecargas.

public static class MoqExtensions { public static IReturnsResult<TMock> ReturnsInOrder<TMock, TResult, T1>(this ISetup<TMock, TResult> setup, params Func<T1, TResult>[] valueFunctions) where TMock : class { var queue = new Queue<Func<T1, TResult>>(valueFunctions); return setup.Returns<T1>(arg => queue.Dequeue()(arg)); } }

Desafortunadamente, usar el método requiere que especifique algunos parámetros de plantilla, pero el resultado es bastante legible.

repository .Setup(x => x.GetPageByUrl<IPageModel>(path)) .ReturnsInOrder(new Func<string, IPageModel>[] { p => null, // Here, the return value can depend on the path parameter p => pageModel.Object, });

Cree sobrecargas para el método de extensión con múltiples parámetros ( T2 , T3 , etc.) si es necesario.


Las respuestas existentes son geniales, pero pensé que lanzaría mi alternativa, que solo usa System.Collections.Generic.Queue y no requiere ningún conocimiento especial del marco de burla, ya que no tenía ninguno cuando lo escribí. ! :)

var pageModel = new Mock<IPageModel>(); IPageModel pageModelNull = null; var pageModels = new Queue<IPageModel>(); pageModels.Enqueue(pageModelNull); pageModels.Enqueue(pageModel.Object);

Entonces...

repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(pageModels.Dequeue);


Puede usar una devolución de llamada cuando configure su objeto simulado. Eche un vistazo al ejemplo de Moq Wiki ( http://code.google.com/p/moq/wiki/QuickStart ).

// returning different values on each invocation var mock = new Mock<IFoo>(); var calls = 0; mock.Setup(foo => foo.GetCountThing()) .Returns(() => calls) .Callback(() => calls++); // returns 0 on first invocation, 1 on the next, and so on Console.WriteLine(mock.Object.GetCountThing());

Tu configuración puede verse así:

var pageObject = pageModel.Object; repository.Setup(x => x.GetPageByUrl<IPageModel>(path)).Returns(() => pageObject).Callback(() => { // assign new value for second call pageObject = new PageModel(); });


Se llegó aquí para el mismo tipo de problema con requisitos ligeramente diferentes.
Necesito obtener diferentes valores de retorno de la simulación basada en diferentes valores de entrada y la solución encontrada que la IMO es más legible ya que utiliza la sintaxis declarativa de Moq (linq a Mocks).

public interface IDataAccess { DbValue GetFromDb(int accountId); } var dataAccessMock = Mock.Of<IDataAccess> (da => da.GetFromDb(It.Is<int>(acctId => acctId == 0)) == new Account { AccountStatus = AccountStatus.None } && da.GetFromDb(It.Is<int>(acctId => acctId == 1)) == new DbValue { AccountStatus = AccountStatus.InActive } && da.GetFromDb(It.Is<int>(acctId => acctId == 2)) == new DbValue { AccountStatus = AccountStatus.Deleted }); var result1 = dataAccessMock.GetFromDb(0); // returns DbValue of "None" AccountStatus var result2 = dataAccessMock.GetFromDb(1); // returns DbValue of "InActive" AccountStatus var result3 = dataAccessMock.GetFromDb(2); // returns DbValue of "Deleted" AccountStatus