我的工作单元最小起订量测试不起作用
My moq test for unit of work doesn't work
我有控制器,它有方法GetAll
(显示所有面霜)
public class AdminController : Controller
{
private readonly ICreamUOW creamUOW;
public AdminController( ICreamUOW creamUOW)
{
this.creamUOW = creamUOW;
}
[HttpGet]
[Authorize(Roles = "Administrator")]
public PartialViewResult TableCreams()
{
return PartialView(creamUOW.Creams.GetAll.ToList());
}
}
我实现了我的存储库的工作单元模式
public class CreamUOW : ICreamUOW
{
private readonly CreamEFDbContext contextDb;
private CreamRepository creamRepository;
public CreamUOW()
{
this.contextDb = new CreamEFDbContext();
}
//properties
public CreamRepository Creams
{
get
{
if (creamRepository == null)
creamRepository = new CreamRepository(contextDb);
return creamRepository;
}
}
}
和他的界面
public interface ICreamUOW : IDisposable
{
CreamRepository Creams { get; }
}
我通过 ninject IoC
绑定此 class 和接口
kernel.Bind<ICreamUOW>().To<CreamUOW>();
(我只展示方法,属性有问题的地方,我在项目中实现了一个dispose方法,不过现在不重要了)
我的通用存储库界面
public interface ICreamRepository<T> where T : class
{
//property
IEnumerable<T> GetAll { get; }
}
和他的实现
public class CreamRepository : ICreamRepository<CreamModel>
{
private CreamEFDbContext context;
public CreamRepository(CreamEFDbContext dbContext)
{
context = dbContext;
}
public IEnumerable<CreamModel> GetAll
{
get { return context.CreamModels.Include(x => x.CreamTypeModel); }
}
}
我尝试进行测试,但它不起作用
[TestMethod]
public void TableCreamContainCreams()
{
//arrange
List<CreamModel> creams = new List<CreamModel>()
{
new CreamModel () { Id = 1, Name = "Test te1", Description = "1" },
new CreamModel () { Id = 2, Name = "Test te2", Description = "2" }
};
private Mock<ICreamUOW> mockCreamUOW = new Mock<ICreamUOW>();
mockCreamUOW.Setup(uow => uow.Creams.GetAll).Returns(creams.ToList());
AdminController controller = new AdminController(null, null, mockCreamUOW.Object);
//action
PartialViewResult resultView = controller.TableCreams();
//assert
Assert.AreEqual(((List<CreamModel>)resultView.Model).Count(), 2);
Assert.IsTrue(((List<CreamModel>)resultView.Model).Count(p => p.Description == "1") == 1);
}
我拿
Message: Test method UnitTests.TestAdminController.TableCreamContainCreams threw exception:
System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: uow => uow.Creams.GetAll
这是什么意思以及如何编写正确的测试?有人可以帮忙吗?
您只能使用 Moq 模拟接口和虚拟方法。
我想我们有两个选择。
一个是在CreamRepository
的GetAll
属性中添加virtual
关键字。
public virtual IEnumerable<CreamModel> GetAll
{
get
{
return context.CreamModels.Include(a => a.CreamTypeModel);
}
}
然后在单元测试中添加另一个 Mock of CreamRepository。
// A mock of CreamRepository, with null passed in because the constructor wants it
Mock<CreamRepository> mockCreamRepository = new Mock<CreamRepository>(null);
// which will return fake data
mockCreamRepository.Setup(mcr => mcr.GetAll).Returns(creams);
// Calling Creams on Mock UOW will give us Mock CreamRepository
// which will in turn give us the fake data if its GetAll is called.
mockCreamUOW.Setup(uow => uow.Creams).Returns(mockCreamRepository.Object);
两个是ICreamUOW
和CreamUOW
returnICreamRepository<CreamModel>
[=21的GetAll
方法=]
public class CreamUOW : ICreamUOW
{
// No changes to the rest of your code
public ICreamRepository<CreamModel> Creams
{
}
}
public interface ICreamUOW : IDisposable
{
// So your interface will be
ICreamRepository<CreamModel> Creams { get; }
}
还有你的单元测试
// Now we are mocking an interface instead of a concrete class like above
Mock<ICreamRepository<CreamModel>> mockCreamRepository = new Mock<ICreamRepository<CreamModel>>();
// The rest is the same
mockCreamRepository.Setup(mcr => mcr.GetAll).Returns(creams);
mockCreamUOW.Setup(uow => uow.Creams).Returns(mockCreamRepository.Object);
但是,正如@sellotape 指出的那样,我不熟悉你对 UOW 和存储库的实现,肯定有问题,因为如果我们正在测试一段调用 A 层的代码,A 层将调用 A 层B,我们应该只需要模拟A层。
如果有帮助请告诉我。
我有控制器,它有方法GetAll
(显示所有面霜)
public class AdminController : Controller
{
private readonly ICreamUOW creamUOW;
public AdminController( ICreamUOW creamUOW)
{
this.creamUOW = creamUOW;
}
[HttpGet]
[Authorize(Roles = "Administrator")]
public PartialViewResult TableCreams()
{
return PartialView(creamUOW.Creams.GetAll.ToList());
}
}
我实现了我的存储库的工作单元模式
public class CreamUOW : ICreamUOW
{
private readonly CreamEFDbContext contextDb;
private CreamRepository creamRepository;
public CreamUOW()
{
this.contextDb = new CreamEFDbContext();
}
//properties
public CreamRepository Creams
{
get
{
if (creamRepository == null)
creamRepository = new CreamRepository(contextDb);
return creamRepository;
}
}
}
和他的界面
public interface ICreamUOW : IDisposable
{
CreamRepository Creams { get; }
}
我通过 ninject IoC
绑定此 class 和接口 kernel.Bind<ICreamUOW>().To<CreamUOW>();
(我只展示方法,属性有问题的地方,我在项目中实现了一个dispose方法,不过现在不重要了)
我的通用存储库界面
public interface ICreamRepository<T> where T : class
{
//property
IEnumerable<T> GetAll { get; }
}
和他的实现
public class CreamRepository : ICreamRepository<CreamModel>
{
private CreamEFDbContext context;
public CreamRepository(CreamEFDbContext dbContext)
{
context = dbContext;
}
public IEnumerable<CreamModel> GetAll
{
get { return context.CreamModels.Include(x => x.CreamTypeModel); }
}
}
我尝试进行测试,但它不起作用
[TestMethod]
public void TableCreamContainCreams()
{
//arrange
List<CreamModel> creams = new List<CreamModel>()
{
new CreamModel () { Id = 1, Name = "Test te1", Description = "1" },
new CreamModel () { Id = 2, Name = "Test te2", Description = "2" }
};
private Mock<ICreamUOW> mockCreamUOW = new Mock<ICreamUOW>();
mockCreamUOW.Setup(uow => uow.Creams.GetAll).Returns(creams.ToList());
AdminController controller = new AdminController(null, null, mockCreamUOW.Object);
//action
PartialViewResult resultView = controller.TableCreams();
//assert
Assert.AreEqual(((List<CreamModel>)resultView.Model).Count(), 2);
Assert.IsTrue(((List<CreamModel>)resultView.Model).Count(p => p.Description == "1") == 1);
}
我拿
Message: Test method UnitTests.TestAdminController.TableCreamContainCreams threw exception: System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: uow => uow.Creams.GetAll
这是什么意思以及如何编写正确的测试?有人可以帮忙吗?
您只能使用 Moq 模拟接口和虚拟方法。
我想我们有两个选择。
一个是在CreamRepository
的GetAll
属性中添加virtual
关键字。
public virtual IEnumerable<CreamModel> GetAll
{
get
{
return context.CreamModels.Include(a => a.CreamTypeModel);
}
}
然后在单元测试中添加另一个 Mock of CreamRepository。
// A mock of CreamRepository, with null passed in because the constructor wants it
Mock<CreamRepository> mockCreamRepository = new Mock<CreamRepository>(null);
// which will return fake data
mockCreamRepository.Setup(mcr => mcr.GetAll).Returns(creams);
// Calling Creams on Mock UOW will give us Mock CreamRepository
// which will in turn give us the fake data if its GetAll is called.
mockCreamUOW.Setup(uow => uow.Creams).Returns(mockCreamRepository.Object);
两个是ICreamUOW
和CreamUOW
returnICreamRepository<CreamModel>
[=21的GetAll
方法=]
public class CreamUOW : ICreamUOW
{
// No changes to the rest of your code
public ICreamRepository<CreamModel> Creams
{
}
}
public interface ICreamUOW : IDisposable
{
// So your interface will be
ICreamRepository<CreamModel> Creams { get; }
}
还有你的单元测试
// Now we are mocking an interface instead of a concrete class like above
Mock<ICreamRepository<CreamModel>> mockCreamRepository = new Mock<ICreamRepository<CreamModel>>();
// The rest is the same
mockCreamRepository.Setup(mcr => mcr.GetAll).Returns(creams);
mockCreamUOW.Setup(uow => uow.Creams).Returns(mockCreamRepository.Object);
但是,正如@sellotape 指出的那样,我不熟悉你对 UOW 和存储库的实现,肯定有问题,因为如果我们正在测试一段调用 A 层的代码,A 层将调用 A 层B,我们应该只需要模拟A层。
如果有帮助请告诉我。