我写这篇文章是因为我已经尝试过一点点解决这个问题而没有运气。我无论出于何种原因都可以找到的每个例子似乎都表明这只是开箱即用,但每当我尝试做同样的事情时,我总会得到错误。基本上,我有一个控制器有两个属性,通过注入。 DI,让我们说吧
public class SomeController
{
private ISomeInterface _i;
private MyConfig _c;
public SomeController(ISomeInterface i, MyConfigContext cxt) // Where cxt is Type of DbContext
{
_i = i;
_c = cxt.Configs.FirstOrDefault();
}
public OkResult PostModel(SomeModel c)
{
// Do things
return Ok();
}
}
在我使用xUnit,Moq和AutoFixture的测试中,我试图避免手动实例化依赖关系B
和C
:
public class SomeControllerTests
{
private MyDbContext _cxt;
private Fixture _fixture;
public SomeControllerTests()
{
_cxt = GetCxt() // GetCxt() just returns a context instance, nothing special
_fixture = new Fixture();
_fixture.Customize(new AutoMoqCustomization { ConfigureMembers = true });
_fixture.Customizations.Add(
new TypeRelay(
typeof(ISomeInterface),
typeof(SomeConcreteClass)
)
);
}
[Fact, AutoData]
public void PostStatus_ReturnsOk_GivenValidRequest()
{
SomeController c = _fixture.Create<SomeController>();
SomeModel m = _fixture.Create<SomeModel>();
var result = c.PostModel(m);
Asset.IsType<OkResult>(result);
}
}
有了上述内容,我在运行测试时得到了NotImplementedException
,它不会告诉我究竟是什么没有实现,所以我无法知道问题是什么。我必须在文档中遗漏一些东西。我想使用AutoFixture使我的测试更耐用,但到目前为止尝试使用它一直很痛苦。我真的不想手动模拟/存储我的整个应用程序只是为了运行测试。理想情况下,我想使用AutoFixture文档中显示的语法,您将测试相关的实例放在测试的参数中,它们是为您创建的,但我没有运气,比如......
[Theory, AutoData]
SomeTestMethod(SomeController c, SomeModel m)
{
var result = c.PostModel(m);
Assert.IsType<OkResult>(result);
}
谢谢阅读 (:
我想这里有两件事情。
首先,我假设您的控制器继承自ControllerBase。 Autofixture似乎无法创建ControllerContext,您可以通过在设置期间注入它的实例来解决此问题。
_fixture.Inject(new ControllerContext());
第二部分涉及具有这种结构的测试
[Theory, AutoData]
SomeTestMethod(SomeController c, SomeModel m)
注入的类型(SomeController和SomeModel)将在调用SomeControllerTests()构造函数之前构造。这意味着夹具定制太晚了。解决这个问题的方法是创建一个自定义AutoDataAttribute,并在那里移动自定义,如下所示:
public class ControllerAutoDataAttribute : AutoDataAttribute
{
public ControllerAutoDataAttribute() : base(() =>
{
var fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
fixture.Customizations.Add(
new TypeRelay(
typeof(ISomeInterface),
typeof(SomeConcreteClass)
)
);
fixture.Inject(new ControllerContext());
return fixture;
}){ }
}
然后更改您的测试方法以使用它:
[Theory, ControllerAutoData]
SomeTestMethod(SomeController c, SomeModel m)
{
var result = c.PostModel(m);
Assert.IsType<OkResult>(result);
}