- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一些遗留代码并针对我对该代码所做的增强编写测试。我有一个类 SiteSession 并提取了一个接口(interface) ISiteSession,因此可以将依赖项注入(inject)调用类。
public class SiteSession : ISiteSession
{
public SiteSession(string userName, string externalRef, IePermitProAdapterClient ePermitService)
{
//.......
}
//...
}
调用类有一个构造函数,其中依赖项被注入(inject)到正在测试的 Controller CustomerDetails 中
private readonly ICustomerDetails _customerDetails;
private ISiteSession _siteSession;
public SsoController(ICustomerDetails customerDetails, ISiteSession siteSession)
{
_customerDetails = customerDetails;
_siteSession = siteSession;
}
public ActionResult CustomerDetails(CustomerDetails customerDetails)
{
//.....
//...
//...
_siteSession = new SiteSession(customer.Username, customer.CustomerRef, ePermitService);
//.....
//...
//...
}
现在我的测试方法已经模拟了依赖关系,我对为这个 Controller 或代码的任何其他部分创建的任何测试都没有问题。但是当这个 Controller 上的测试CustomerDetails
被调用时,实际的构造函数调用是对 SiteSession
进行的类,我无法注入(inject)模拟并中断真实的调用。我的测试代码如下:
private Mock<ISiteSession> _siteSession;
在测试设置方法中:_siteSession = new Mock<ISiteSession>();
并在测试方法中:_siteSession.Setup(x => x.Token).Returns("TestToken");
我试过类似的方法:
_siteSession = new Mock<SiteSession>(_customer.Object.Username, _customer.Object.CustomerRef, null);
由于转换类型不同,这显然是不正确的,我想不出如何模拟 SiteSession 类,以便不调用实际的构造函数。我正在使用 NInject、NUnit 和 Moq
最佳答案
这是一个设计问题。通过在 Controller 中手动创建实例, Controller 与实现紧密耦合,这使得模拟变得非常困难。检查您的设计选择,因为当前示例在最终目标方面不是很清楚。
难以提供适当的单元测试应该是设计问题的直接指标。
也就是说,根据当前的设计,如果您可以控制 Controller ,您可能需要 session 提供程序
public interface ISiteSessionProvider {
ISiteSession CreateSiteSession(CustomerDetails customerDetails);
}
Controller 将明确依赖于哪些
public class SsoController: Controller {
private readonly ICustomerDetails _customerDetails;
private readonly ISiteSessionProvider siteSessionProvider;
public SsoController(ICustomerDetails customerDetails, ISiteSessionProvider siteSessionProvider) {
_customerDetails = customerDetails;
this.siteSessionProvider = siteSessionProvider;
}
public ActionResult CustomerDetails(CustomerDetails customerDetails) {
//...
ISiteSession siteSession = siteSessionProvider.CreateSiteSession(customerDetails);
//...
}
}
单元测试现在需要您模拟所需的行为
//Arrange
var sessionMock = new Mock<ISiteSession>();
sessionMock.Setup(_ => _.Token).Returns("TestToken");
var providerMock = new Mock<ISiteSessionProvider>();
providerMock
.Setup(_ => _.CreateSiteSession(It.IsAny<CustomerDetails>()))
.Returns(sessionMock.Object);
var controller = new SsoController(Mock.Of<ICustomerDetails>(), providerMock.Object);
//Act
var result = controller.CustomerDetails(...);
//Assert
//...
提供者的实现然后可以处理实现问题
public ISiteSession CreateSiteSession(CustomerDetails customerDetails) {
//...
return new SiteSession(customer.Username, customer.CustomerRef, ePermitService);
}
关于c# - 如何模拟在被测方法中实例化的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50465386/
我是一名优秀的程序员,十分优秀!