Asp.net mvc 我不熟悉单元测试,我';I’我想知道为什么它不起作用
我是MVC和单元测试的新手,所以我一直在遵循指南等 目前,我正在研究单元测试。我有一个测试,据我所知应该是有效的,但不幸的是没有Asp.net mvc 我不熟悉单元测试,我';I’我想知道为什么它不起作用,asp.net-mvc,unit-testing,xunit,Asp.net Mvc,Unit Testing,Xunit,我是MVC和单元测试的新手,所以我一直在遵循指南等 目前,我正在研究单元测试。我有一个测试,据我所知应该是有效的,但不幸的是没有 using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using WorkingWithVisualStudio.Controllers.Home; using WorkingWithVisualStudio.Models; using Xunit; namespace Workin
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using WorkingWithVisualStudio.Controllers.Home;
using WorkingWithVisualStudio.Models;
using Xunit;
namespace WorkingWithVisualStudio.Tests
{
public class HomeControllerTests
{
class ModelCompleteFakeRepository : IRepository
{
public IEnumerable<Product> Products { get; } = new Product[] {
new Product { Name = "P1", Price = 275M },
new Product { Name = "P2", Price = 48.95M },
new Product { Name = "P3", Price = 19.50M },
new Product { Name = "P3", Price = 34.95M }};
public void AddProduct(Product p)
{
// do nothing - not required for test
}
}
[Fact]
public void IndexActionModelIsComplete()
{
// Arrange
var controller = new HomeController();
controller.Repository = new ModelCompleteFakeRepository();
// Act
var model = (controller.Index() as ViewResult)?.ViewData.Model
as IEnumerable<Product>;
// Assert
Assert.Equal(controller.Repository.Products, model,
Comparer.Get<Product>((p1, p2) => p1.Name == p2.Name
&& p1.Price == p2.Price));
}
class ModelCompleteFakeRepositoryPricesUnder50 : IRepository
{
public IEnumerable<Product> Products { get; } = new Product[] {
new Product { Name = "P1", Price = 5M },
new Product { Name = "P2", Price = 48.95M },
new Product { Name = "P3", Price = 19.50M },
new Product { Name = "P3", Price = 34.95M }};
public void AddProduct(Product p)
{
// do nothing - not required for test
}
}
[Fact]
public void IndexActionModelIsCompletePricesUnder50()
{
// Arrange
var controller = new HomeController();
controller.Repository = new ModelCompleteFakeRepositoryPricesUnder50();
// Act
var model = (controller.Index() as ViewResult)?.ViewData.Model
as IEnumerable<Product>;
// Assert
Assert.Equal(controller.Repository.Products, model,
Comparer.Get<Product>((p1, p2) => p1.Name == p2.Name
&& p1.Price == p2.Price));
}
}
}
我的存储库:
public class SimpleRepository : IRepository
{
private static SimpleRepository sharedRepository = new SimpleRepository();
private Dictionary<string, Product> products = new Dictionary<string, Product>();
public static SimpleRepository SharedRepository => sharedRepository;
public SimpleRepository()
{
var initialItems = new[]
{
new Product {Name = "Kayak", Price = 275M},
new Product { Name = "Lifejacket", Price = 48.95M },
new Product { Name = "Soccer ball", Price = 19.50M },
new Product { Name = "Corner flag", Price = 34.95M }
};
foreach(var p in initialItems)
{
AddProduct(p);
}
//products.Add("Error", null);
}
public IEnumerable<Product> Products => products.Values;
public void AddProduct(Product p) => products.Add(p.Name, p);
}
如果这看起来是一个愚蠢的问题,我很抱歉,但我刚刚开始研究单元测试。如果有人能向我解释问题所在,我将不胜感激。非常感谢那些花时间帮忙的人。因为在您的
索引
方法中,您指的是SimpleRepository
,而不是存储库
成员
替换
public IActionResult Index() => View(SimpleRepository.SharedRepository.Products);
与
我还应该补充一点,您可能希望查看代码的结构,并将存储库注入构造函数中。另外,两个不同的测试测试相同的东西,所以只需要其中一个
编辑:我的答案解决了您当前的问题,@Nkosi answer显示了您应该如何正确地执行此操作。因为在您的
索引
方法中,您指的是SimpleRepository
,而不是存储库
成员
替换
public IActionResult Index() => View(SimpleRepository.SharedRepository.Products);
与
我还应该补充一点,您可能希望查看代码的结构,并将存储库注入构造函数中。另外,两个不同的测试测试相同的东西,所以只需要其中一个
编辑:我的答案解决了您当前的问题,而@Nkosi answer显示了您应该如何正确地执行此操作。我首先建议您使用 方法和类应该明确地要求(通常通过方法参数或构造函数参数)它们需要的任何协作对象才能正常工作 所以控制器最终会变成这样
public class HomeController : Controller {
private readonly IRepository repository;
public HomeController(IRepository repository) {
this.repository = repository;
}
public IActionResult Index() => View(repository.Products.ToList());
[HttpGet]
public IActionResult AddProduct() => View(new Product());
[HttpPost]
public IActionResult AddProduct(Product p) {
repository.AddProduct(p);
return RedirectToAction("Index");
}
}
以避免在独立单元测试期间访问共享存储库时最初犯下的错误,该错误导致您的断言失败
尽量避免将类与静态或共享依赖项紧密耦合。注入这种依赖的抽象会更安全
测试的简化版本现在可以清楚地执行如下操作
class ModelCompleteFakeRepository : IRepository {
public IEnumerable<Product> Products { get; } = new Product[] {
new Product { Name = "P1", Price = 275M },
new Product { Name = "P2", Price = 48.95M },
new Product { Name = "P3", Price = 19.50M },
new Product { Name = "P3", Price = 34.95M }
};
public void AddProduct(Product p) {
// do nothing - not required for test
}
}
[Fact]
public void IndexActionModelIsComplete() {
// Arrange
var repository = new ModelCompleteFakeRepository();
var controller = new HomeController(repository);
var expected = repository.Products;
// Act
var actual = (controller.Index() as ViewResult)?.ViewData.Model as IEnumerable<Product>;
// Assert
Assert.IsNotNull(actual);
Assert.Equal(expected, actual);
}
class ModelCompleteMakeRepository:IRepository{
公共IEnumerable产品{get;}=新产品[]{
新产品{Name=“P1”,价格=275M},
新产品{Name=“P2”,价格=4895M},
新产品{Name=“P3”,价格=19.50M},
新产品{Name=“P3”,价格=3495万}
};
公共产品(产品p){
//不做任何事情-测试不需要
}
}
[事实]
public void IndexActionModelIsComplete(){
//安排
var repository=new ModelCompleteFakeRepository();
var控制器=新的HomeController(存储库);
var预期=repository.Products;
//表演
var actual=(controller.Index()作为ViewResult)?.ViewData.Model作为IEnumerable;
//断言
Assert.IsNotNull(实际值);
断言。相等(预期、实际);
}
我首先建议您使用
方法和类应该明确地要求(通常通过方法参数或构造函数参数)它们需要的任何协作对象才能正常工作
所以控制器最终会变成这样
public class HomeController : Controller {
private readonly IRepository repository;
public HomeController(IRepository repository) {
this.repository = repository;
}
public IActionResult Index() => View(repository.Products.ToList());
[HttpGet]
public IActionResult AddProduct() => View(new Product());
[HttpPost]
public IActionResult AddProduct(Product p) {
repository.AddProduct(p);
return RedirectToAction("Index");
}
}
以避免在独立单元测试期间访问共享存储库时最初犯下的错误,该错误导致您的断言失败
尽量避免将类与静态或共享依赖项紧密耦合。注入这种依赖的抽象会更安全
测试的简化版本现在可以清楚地执行如下操作
class ModelCompleteFakeRepository : IRepository {
public IEnumerable<Product> Products { get; } = new Product[] {
new Product { Name = "P1", Price = 275M },
new Product { Name = "P2", Price = 48.95M },
new Product { Name = "P3", Price = 19.50M },
new Product { Name = "P3", Price = 34.95M }
};
public void AddProduct(Product p) {
// do nothing - not required for test
}
}
[Fact]
public void IndexActionModelIsComplete() {
// Arrange
var repository = new ModelCompleteFakeRepository();
var controller = new HomeController(repository);
var expected = repository.Products;
// Act
var actual = (controller.Index() as ViewResult)?.ViewData.Model as IEnumerable<Product>;
// Assert
Assert.IsNotNull(actual);
Assert.Equal(expected, actual);
}
class ModelCompleteMakeRepository:IRepository{
公共IEnumerable产品{get;}=新产品[]{
新产品{Name=“P1”,价格=275M},
新产品{Name=“P2”,价格=4895M},
新产品{Name=“P3”,价格=19.50M},
新产品{Name=“P3”,价格=3495万}
};
公共产品(产品p){
//不做任何事情-测试不需要
}
}
[事实]
public void IndexActionModelIsComplete(){
//安排
var repository=new ModelCompleteFakeRepository();
var控制器=新的HomeController(存储库);
var预期=repository.Products;
//表演
var actual=(controller.Index()作为ViewResult)?.ViewData.Model作为IEnumerable;
//断言
Assert.IsNotNull(实际值);
断言。相等(预期、实际);
}
显示正在测试的方法。您试图测试的预期行为是什么?我已经更新了我的问题,显示了正在测试的方法。你想要测试的行为是什么?我已经更新了我的问题,非常感谢。你让我想了很多,非常感谢。你让我想了很多。
public IActionResult Index() => View(Repository.Products);
public class HomeController : Controller {
private readonly IRepository repository;
public HomeController(IRepository repository) {
this.repository = repository;
}
public IActionResult Index() => View(repository.Products.ToList());
[HttpGet]
public IActionResult AddProduct() => View(new Product());
[HttpPost]
public IActionResult AddProduct(Product p) {
repository.AddProduct(p);
return RedirectToAction("Index");
}
}
class ModelCompleteFakeRepository : IRepository {
public IEnumerable<Product> Products { get; } = new Product[] {
new Product { Name = "P1", Price = 275M },
new Product { Name = "P2", Price = 48.95M },
new Product { Name = "P3", Price = 19.50M },
new Product { Name = "P3", Price = 34.95M }
};
public void AddProduct(Product p) {
// do nothing - not required for test
}
}
[Fact]
public void IndexActionModelIsComplete() {
// Arrange
var repository = new ModelCompleteFakeRepository();
var controller = new HomeController(repository);
var expected = repository.Products;
// Act
var actual = (controller.Index() as ViewResult)?.ViewData.Model as IEnumerable<Product>;
// Assert
Assert.IsNotNull(actual);
Assert.Equal(expected, actual);
}