单元测试和使用 Moq 中的问题。Returns
Issue in unit testing and using Moq .Returns
我是编写单元测试的新手。因此,我一直在苦苦挣扎。
我需要通过外部网络服务插入产品。然后 WebService 将 return 之后更新产品所必需的字符串。
这是我的 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));
}
}
但是当我调试测试时,这一行的结果是空的,这是不正确的。
string result = this._WebService.Add(product.ID, DateTime.Now);
这一行不应该处理 _WebService.Add() 和 return“0”的行为吗?
_WebService.Setup(b => b.Add(1, DateTime.Now))
.Returns("0");
我知道我写错了测试,但我不知道该怎么办。
谢谢。
这里的问题是你在模拟调用静态方法 `DateTime.Now' 。但是"Now"在mocking的时间点和as it called是不一样的。因此你的电话没有 return 任何东西。
我可以建议以下 3 种方式:
1) 调用是否使用 DateTime.Now
对你来说并不重要,在这种情况下你可以忽略第二个参数:
_WebService.Setup(b => b.Add(1, It.IsAny<DateTime>())).Returns("0");
2) 您想测试呼叫是与 DateTime.Now
进行的。在那种情况下,我创建了一个 interface
来获取 DateTime.Now
:
public interface IDateTimeNowProvider
{
DateTime Now { get; }
}
public ProductController(IProductRepository productRepository,
IWebService webService,
IDateTimeNowProvider dateTimeNowProvider)
{
_ProductRepository = productRepository;
_WebService = webService;
_dateTimeNowProvider = dateTimeNowProvider;
}
在生产代码中,您使用它的默认实现,即 returns DateTime.Now
。但是在你的测试中 class 你用一些预定义的值来模拟这个接口并且你测试使用这个值。
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 isolator
我是编写单元测试的新手。因此,我一直在苦苦挣扎。
我需要通过外部网络服务插入产品。然后 WebService 将 return 之后更新产品所必需的字符串。
这是我的 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));
}
}
但是当我调试测试时,这一行的结果是空的,这是不正确的。
string result = this._WebService.Add(product.ID, DateTime.Now);
这一行不应该处理 _WebService.Add() 和 return“0”的行为吗?
_WebService.Setup(b => b.Add(1, DateTime.Now))
.Returns("0");
我知道我写错了测试,但我不知道该怎么办。
谢谢。
这里的问题是你在模拟调用静态方法 `DateTime.Now' 。但是"Now"在mocking的时间点和as it called是不一样的。因此你的电话没有 return 任何东西。
我可以建议以下 3 种方式:
1) 调用是否使用 DateTime.Now
对你来说并不重要,在这种情况下你可以忽略第二个参数:
_WebService.Setup(b => b.Add(1, It.IsAny<DateTime>())).Returns("0");
2) 您想测试呼叫是与 DateTime.Now
进行的。在那种情况下,我创建了一个 interface
来获取 DateTime.Now
:
public interface IDateTimeNowProvider
{
DateTime Now { get; }
}
public ProductController(IProductRepository productRepository,
IWebService webService,
IDateTimeNowProvider dateTimeNowProvider)
{
_ProductRepository = productRepository;
_WebService = webService;
_dateTimeNowProvider = dateTimeNowProvider;
}
在生产代码中,您使用它的默认实现,即 returns DateTime.Now
。但是在你的测试中 class 你用一些预定义的值来模拟这个接口并且你测试使用这个值。
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 isolator