Почему я получаю исключение NullReferenceException при попытке обратиться к объекту Moq в модульном тестировании? - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть два класса:

  • ProductController класс с SingleProduct действием
  • Helper класс с собственным методом getProduct(ProductsContext db, string id), который получает указанный продукт из базы данных

Я пытаюсь создать модульный тест для действия SingleProduct с использованием инфраструктуры Moq.Я создаю макет для Helper объекта, но при запуске теста я получаю NullReferenceException для смоделированного Helper объекта.

Что я делаю не так?

[TestMethod]
public void ProductNotFoundTest()
{
    var mockHelper = new Mock<Helper>();
    mockHelper.Setup(h => h.getProduct(It.IsAny<ProductsContext>(), It.IsAny<string>())).Returns(It.IsAny<Product>());

    ProductController controller = new ProductController(mockHelper.Object);

    ViewResult result = controller.SingleProduct("i'm not exist") as ViewResult;
    Assert.AreEqual("~/Views/Product/ProductNotFound.cshtml", result.ViewName);
}

namespace OnlineStoreParser.Controllers
{
    public class ProductController : Controller
    {
        private Helper _h;        

        public ProductController(Helper h)
        {
            Helper _h = h;
        }

        public ProductController()
        {
            _h = new Helper();
        }

        public ActionResult SingleProduct(string id)
        {            
            Product product;

            using (var context = new ProductsContext())
            {
                // Find product with specified ID
                product = _h.getProduct(context, id);

                if(product != null)
                {
                    ViewBag.History = product.History;
                    ViewBag.Images = product.Photos;
                    return View(product);
                }                
                else
                {
                    return View("~/Views/Product/ProductNotFound.cshtml");
                }
            }
       }
   }   
}  

namespace OnlineStoreParser.Models
{
    public class Helper
    {
        public Helper() { }

        public virtual Product getProduct(ProductsContext db, string id)
        {
            return db.Products.SingleOrDefault(p => p.ProductId == id);
        }
    }
}  

1 Ответ

0 голосов
/ 20 сентября 2018

Измените свой конструктор на это.

private Helper _h;    
private ProductsContext _productsContext;

public ProductController(Helper h, ProductsContext productsContext)
{
    _h = h;
    _productsContext = productsContext;
}

У вас было две ошибки.

В

using (var context = new ProductsContext())

вы создаете новый ProductsContext в своем коде;даже в вашем тесте, который является плохой практикой, потому что вы тоже не хотите тестировать зависимости.

И в вашем конструкторе вы делаете

public ProductController(Helper h)
{
    Helper _h = h;
}

, что не то, что вам нужносделать.Вы хотите установить переменную _h = h; и не создавать новую (которая недоступна вне конструктора, что означает, что в вашем методе SingleProduct ваша переменная _h не установлена ​​должным образом.

Последнее, ноне в последнюю очередь вы не должны возвращать It.IsAny<Product>() в своем макете. Верните новый экземпляр. Или для теста просто null.

Еще один совет: вы используете ProductsContext только в вашем Helper.Было бы разумно удалить его из ProductController и добавить его к вашему ProductsContext в конструкторе, как я предлагал сделать с Helper в ProductsController, потому что вашему ProductsController теперь не нужно ProductsContextна все.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...