单元测试和使用Moq .Returns的问题(Issue in unit testing and using Moq .Returns)

编程入门 行业动态 更新时间:2024-10-26 19:26:47
单元测试和使用Moq .Returns的问题(Issue in unit testing and using Moq .Returns)

我是新手编写单元测试。 因此,我一直在努力。

我需要通过外部WebService插入产品。 然后,WebService将返回一个后续更新产品所必需的字符串。

这是我的ApiController :

public class ProductController : ApiController { private IProductRepository _ProductRepository; private IWebService _WebService; public ProductController(IProductRepository productRepository, IWebService webService) { _ProductRepository = productRepository; _WebService = webService; } public HttpResponseMessage Add(string title) { using (TransactionScope scope = new TransactionScope()) { Product product = new Product { Title = title }; this._ProductRepository.Add(product); // WebService will return a string string result = this._WebService.Add(product.ID, DateTime.Now); product.ServiceResult = result; this._ProductRepository.Update(product); scope.Complete(); } return Request.CreateResponse(HttpStatusCode.Created); } }

我想知道如何为此代码编写单元测试?

我试着按如下方式编写它:(使用NUnit,Moq)

[TestFixture] public class ProductControllerShould : AssertionHelper { private Mock<IWebService> _WebService; private Mock<IProductRepository> _ProductRepository; [SetUp] public void Setup() { _WebService = new Mock<IWebService>(); _ProductRepository = new Mock<IProductRepository>(); } [Test] public void ReturnCreatedOnAdd() { _WebService.Setup(b => b.Add(1, DateTime.Now)) .Returns("0"); var controller = new ProductController(_ProductRepository.Object, _WebService.Object); var result = controller.Add("Lumia"); Expect(result, Is.EqualTo(HttpStatusCode.Created)); } }

但是当我调试测试时,此行的结果为null,这是不正确的。

string result = this._WebService.Add(product.ID, DateTime.Now);

这行不应该处理_WebService.Add()的行为并返回“0”吗?

_WebService.Setup(b => b.Add(1, DateTime.Now)) .Returns("0");

我知道我错误地写了测试,但我不知道该怎么做。

谢谢。

I am new to write Unit Tests. Therefore, I have been struggling with.

I need to insert product via an external WebService. Then the WebService will return a string that is necessary to update the product afterwards.

This is my ApiController:

public class ProductController : ApiController { private IProductRepository _ProductRepository; private IWebService _WebService; public ProductController(IProductRepository productRepository, IWebService webService) { _ProductRepository = productRepository; _WebService = webService; } public HttpResponseMessage Add(string title) { using (TransactionScope scope = new TransactionScope()) { Product product = new Product { Title = title }; this._ProductRepository.Add(product); // WebService will return a string string result = this._WebService.Add(product.ID, DateTime.Now); product.ServiceResult = result; this._ProductRepository.Update(product); scope.Complete(); } return Request.CreateResponse(HttpStatusCode.Created); } }

I was wondering how should I write a unit test for this code?

I've tried to write it as follows: (with NUnit, Moq)

[TestFixture] public class ProductControllerShould : AssertionHelper { private Mock<IWebService> _WebService; private Mock<IProductRepository> _ProductRepository; [SetUp] public void Setup() { _WebService = new Mock<IWebService>(); _ProductRepository = new Mock<IProductRepository>(); } [Test] public void ReturnCreatedOnAdd() { _WebService.Setup(b => b.Add(1, DateTime.Now)) .Returns("0"); var controller = new ProductController(_ProductRepository.Object, _WebService.Object); var result = controller.Add("Lumia"); Expect(result, Is.EqualTo(HttpStatusCode.Created)); } }

but when I debug the test, result in this line is null that is not correct.

string result = this._WebService.Add(product.ID, DateTime.Now);

Shouldn't this line handle the behaviour of _WebService.Add() and return "0"?

_WebService.Setup(b => b.Add(1, DateTime.Now)) .Returns("0");

I know I write the test incorrectly but I don't know what should I do.

Thanks.

最满意答案

这里的问题是你正在模拟静态方法`DateTime.Now'的调用。 但是,在嘲笑的时间点上的“现在”和它被称为是不同的。 因此,您的电话不会返回任何内容。

我可以建议以下三种方式:

1)如果调用是在DateTime.Now与否,那对你来说并不重要,在这种情况下你可以忽略第二个参数:

_WebService.Setup(b => b.Add(1, It.IsAny<DateTime>())).Returns("0");

2)你想测试,调用是使用DateTime.Now 。 在这种情况下,我创建一个获取DateTime.Now的interface :

public interface IDateTimeNowProvider { DateTime Now { get; } } public ProductController(IProductRepository productRepository, IWebService webService, IDateTimeNowProvider dateTimeNowProvider) { _ProductRepository = productRepository; _WebService = webService; _dateTimeNowProvider = dateTimeNowProvider; }

在生产代码中,您使用它的默认实现,它只返回D ateTime.Now 。 但是在您的测试类中,您使用某些预定义值模拟此接口,并测试是否使用此值。

var now = DateTime.Parse("2017-01-22"); var _dateTimeNowProvider = new Mock<IDateTimeNowProvider>(); var controller = new ProductController(_ProductRepository.Object, _WebService.Object, _dateTimeNowProvider.Object ); _dateTimeNowProvider.Setup(x => x.Now).Returns(now); _WebService.Setup(b => b.Add(1,now)).Returns("0");

3)您可以使用允许模拟静态方法的特殊模拟框架,例如typemock隔离器

The problem here, is that you are mocking call of static method `DateTime.Now' . But "Now" in the time point of mocking and as it is called are different. Therefore your call doesn't return anything.

I could suggest 3 following ways:

1) It doesn't really matter for you, if the call was with DateTime.Now or not, in that case you could ignore the second argument:

_WebService.Setup(b => b.Add(1, It.IsAny<DateTime>())).Returns("0");

2) You want to test, that the call was with DateTime.Now. In that case i create an interface for getting DateTime.Now:

public interface IDateTimeNowProvider { DateTime Now { get; } } public ProductController(IProductRepository productRepository, IWebService webService, IDateTimeNowProvider dateTimeNowProvider) { _ProductRepository = productRepository; _WebService = webService; _dateTimeNowProvider = dateTimeNowProvider; }

In production code you use default implementation of it, that just returns DateTime.Now. But in your test class you do mock this interface with some predefined values and you test for using this value.

var now = DateTime.Parse("2017-01-22"); var _dateTimeNowProvider = new Mock<IDateTimeNowProvider>(); var controller = new ProductController(_ProductRepository.Object, _WebService.Object, _dateTimeNowProvider.Object ); _dateTimeNowProvider.Setup(x => x.Now).Returns(now); _WebService.Setup(b => b.Add(1,now)).Returns("0");

3) You could use special mocking framework that allows to mock static methods, as for example typemock isolator

更多推荐

本文发布于:2023-07-31 08:57:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1341935.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:单元测试   Moq   Returns   testing   unit

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!