[英]Testing property used on mvc controller after injection
public class MyUser: IIdentity, IMyUser{
// ommited for abbrev.
}
public interface IMyUser
{
int Id { get; set; }
int? CompanyId { get; set; }
}
在MyController内部,我正在使用MyUser和其他用户来填充组合框
public ActionResult Details(int? subsidId = null, int? req = null)
{
...
MyUser user = this.User.GetInfo();
var obj1 = ... // ommited on purpose for abbrev.
populateCombos(subsidId, user.CompanyId, req);
}
我在这行populateCombos上遇到异常,因为用户对象始终为null。 在同一个控制器中,我正在注入IMyUser实现的接口
[Inject]
public IMyUser MyUser { get; set; }
使用ninject
正确绑定了此属性(就像我的应用中的其他属性一样)
kernel.Bind<IMyUser>().To<MyUser>().InRequestScope();
现在在测试项目上,我正在通过模拟请求的依赖项初始化控制器
[SetUp]
public void Setup()
{
_controller = new MyController(){
... repositories....
MyUser = MockMyUser()
}
}
private IMyUser MockMyUser()
{
var u = new Mock<IMyUser>();
u.SetupGet(x => x.Id).Returns(1);
u.SetupGet(x => x.CompanyId).Returns(99);
return u.Object;
}
在内部测试方法中,我编写了简单的测试
[Test]
public void CanDoDetails()
{
ViewResult res = this.controller.Details(1, 2) as ViewResult;
var model = result.Model as MyModel;
Assert.IsNotNull(model);
}
问题是:
为什么我得到这个依赖关系(
MyUser
内MyController
为null
),因为它是正确的注射? 我做错了什么?
更新:
public static MyUser GetInfo(this IPrincipal principal)
{
if (principal != null)
{
return principal.Identity as MyUser;
}
return null;
}
更新2:基于Nkosi的答案,我进行了以下更改
public interface IMyUser : IIdentity { ... }
内部详细信息ActionMethod控制器
IMyUser user = this.User.GetInfo();
并在测试方法下
[SetUp]
public void Setup()
{
var mockUser = MockMyUser();
string[] roles = new[] { "Admin", "SuperUser" };
_controller = new MyController()
{
....
MyUser = this.MockMyUser(),
ControllerContext = new ControllerContext() {
Controller = _controller,
RequestContext = new RequestContext(new MockHttpContext(mockUser, roles), new RouteData())
}
}
}
but I'm still getting `IMyUser user = this.User.GetInfo();` `this.User` is still null.
ps我还更改了GetInfo以返回IMyUser
而不是MyUser
。
那模拟控制器又如何呢?
Mock<MyController> mockController = new Mock<MyController>();
mockController.SetupGet(t => t.MyUser).Returns(MockMyUser());
然后您可以通过模拟控制器.Object访问控制器并尝试进行测试。
我的建议也将是使IMyUser
继承IIdentity
public class MyUser: IMyUser {
// ommited for abbrev.
}
public interface IMyUser: IIdentity {
int Id { get; set; }
int? CompanyId { get; set; }
}
如果您使用的是Controller.User { get; }
则要使单元测试正常工作Controller.User { get; }
Controller.User { get; }
是为控制器创建模拟/伪造用户。 为了获得对User的访问权限(只读),您必须创建一个模拟HttpContext
。 y 幸运的是,您仍然只希望访问该User
。
private class MockHttpContext : HttpContextBase {
private readonly IPrincipal user;
public MockHttpContext(IIdentity identity , string[] roles = null) {
var principal = new GenericPrincipal(identity, roles ?? new string[] { });
user = principal;
}
public override IPrincipal User {
get {
return user;
}
set {
base.User = value;
}
}
}
您可以设置主体以适合您的身份验证设置,以及在运行时提出的声明。 这只是一个例子。
[SetUp]
public void Setup()
{
string[] roles = new[] { "Admin", "SuperUser" };
var mockUser = MockMyUser();
_controller = new MyController(){
... repositories....
MyUser = mockUser
};
_controller.ControllerContext = new ControllerContext() {
Controller = _controller,
RequestContext = new RequestContext(new MockHttpContext(mockUser, roles), new RouteData())
};
}
private IMyUser MockMyUser()
{
var u = new Mock<IMyUser>();
u.Setup(x => x.Name).Returns("username@test.io");
u.Setup(x => x.Id).Returns(1);
u.Setup(x => x.CompanyId).Returns(99);
return u.Object;
}
现在应该允许
public static IMyUser GetInfo(this IPrincipal principal) {
if (principal != null) {
return principal.Identity as IMyUser;
}
return null;
}
以principal.Identity as IMyUser
返回principal.Identity as IMyUser
不为空。
我使用上面提供的内容重新创建了测试的最低版本,并且能够测试并通过。
[TestClass]
public class MyUserDependentControllerTest {
[TestMethod]
public void CanDoDetails() {
//Arrange
string[] roles = new[] { "Admin", "SuperUser" };
var u = new Mock<IMyUser>();
u.Setup(x => x.Name).Returns("username@test.io");
u.Setup(x => x.Id).Returns(1);
u.Setup(x => x.CompanyId).Returns(99).Verifiable();
var mockUser = u.Object;
var controller = new MyController() {
//... repositories....
MyUser = mockUser
};
controller.ControllerContext = new ControllerContext() {
Controller = controller,
RequestContext = new RequestContext(new MockHttpContext(mockUser, roles), new RouteData())
};
//Act
var result = controller.Details(1, 2);
//Assert
var viewResult = result as ViewResult;
Assert.IsNotNull(viewResult);
var model = viewResult.Model as MyModel;
Assert.IsNotNull(model);
u.Verify();
}
public class MyController : Controller {
public ActionResult Details(int? subsidId = null, int? req = null) {
//...
var user = this.User.GetInfo();
//
populateCombos(subsidId, user.CompanyId, req);
//this is just for matching test expectations
var model = new MyModel();
return View(model);
}
private void populateCombos(int? subsidId, int? nullable, int? req) {
//Empty as I have no clue what happens in here
}
public IMyUser MyUser { get; set; }
}
public class MyModel { }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.