我是 AutoFixture 的新手,正在尝试为团队中不太喜欢 TDD 的开发人员在我的测试环境上创建一个友好的扩展。这是代码:
public class HomeController : Controller
{
private readonly ISomeService _someService;
public HomeController(ISomeService someService)
{
_someService = someService;
}
public ActionResult Index()
{
_someService.SomeMethod();
return View("Index");
}
}
public class ControllerContext<T> where T : Controller
{
protected static T ControllerUnderTest;
private static IFixture _fixture;
public ControllerContext()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_fixture.Customize<ControllerContext>(c => c.Without(x => x.DisplayMode));
ControllerUnderTest = _fixture.Create<T>();
}
protected static Mock<TDouble> For<TDouble>() where TDouble : class
{
//var mock = _fixture.Create<TDouble>();
var mock = _fixture.Create<Mock<TDouble>>();
return mock;
}
}
所以扩展是 For
方法 - 当我检查具有注入(inject)的“ISomeService”的 ControllerUnderTest
时,它有一个很好的实例注入(inject),并且它肯定会调用该方法我断言反对。当我检查“For”方法中创建的模拟时,它似乎与注入(inject) Controller 的版本相同,但它不会Verif
y!
public class EXAMPLE_When_going_to_home_page : ControllerContext<HomeController>
{
Because of = () =>
{
ControllerUnderTest.Index();
};
It should_do_something = () =>
{
//This throws a 'Invocation was not performed'
For<ISomeService>().Verify(x => x.SomeMethod());
};
Establish context = () =>
{
};
}
我正在努力寻找有人做类似事情的例子,我知道我肯定在这里做了一些愚蠢的事情,但在我看来,这个测试应该通过?
最佳答案
Create
每次都会创建一个新的匿名实例,除非您卡住(通过 .Freeze<T>()
或 AutoFixture.Xunit 的 [Frozen]
)实例。这意味着注入(inject) HomeController
的值与 For
返回的不同.
有几种可能的解决方案,所有这些最终都将涉及卡住该值或注入(inject)要使用的值。
一个示例如下所示:
public class ControllerContext<T> where T : Controller
{
private static Lazy<T> _controllerFactory;
private static IFixture _fixture;
public ControllerContext()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_fixture.Customize<ControllerContext>(c => c.Without(x => x.DisplayMode));
_controllerFactory = new Lazy<T>(() => _fixture.Create<T>());
}
protected static Mock<TDouble> For<TDouble>() where TDouble : class
{
var mock = _fixture.Freeze<Mock<TDouble>>();
return mock;
}
protected static T ControllerUnderTest
{
get { return _controllerFactory.Value; }
}
}
public class EXAMPLE_When_going_to_home_page : ControllerContext<HomeController>
{
static Mock<ISomeService> SomeService;
Because of = () =>
{
SomeService = For<ISomeService>();
ControllerUnderTest.Index();
};
It should_do_something = () =>
{
//This throws a 'Invocation was not performed'
SomeService.Verify(x => x.SomeMethod());
};
Establish context = () =>
{
};
}
这个更改版本的重点是首先 Freeze
仅在创建 Controller 的匿名实例之后才在服务模拟上调用。因为For
的方式现在使用方法,您可能应该将其重命名为 GetService
.
关于c# - 在通用测试助手中管理由 AutoFixture 馈送到 MVC Controller 的服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18955717/