簡體   English   中英

單元測試模擬控制器,C#我需要模擬HTTPContext嗎? 我要嘲笑什么方法?

[英]Unit Test Mock Controller, C# Do I need to Mock HTTPContext? What methods do I mock?

我的任務是為數據庫中的某些代碼編寫單元測試。 單元測試必須模擬所有內容,並測試通過和失敗的情況。 目前,我正在使用NUnit和FakeItEasy,過去我曾經使用過Moq,所以不介意再次使用它。

調節器

public class AccountController : BaseController
{
    private readonly IAccountsManager _accountsManager;
    private readonly ICallerInfoManager _callerInfoManager;

    public AccountController(IAccountsManager accountsManager, ICallerInfoManager callerInfoManager)
        : base(callerInfoManager)
    {
        _accountsManager = accountsManager;
        _callerInfoManager = callerInfoManager;
    }

    [HttpGet]
    [ActionName("GetAll")]
    public List<Account> Get()
    {
        var context = _callerInfoManager.GetFromHttpContext();
        return _accountsManager.GetAll(context.SiteLocationCode);
    }

    [HttpPost]
    [ActionName("Search")]
    public List<Account> Search(AccountRequest request)
    {
        var context = _callerInfoManager.GetFromHttpContext();
        return _accountsManager.GetAllWithNameContaining(request.SearchTerm, context.SiteLocationCode);
    }
}

CallerInfoManager

 public class CallerInfoManager : ICallerInfoManager
{
    private readonly IContactContextManager _contactContextManager;
    private const string ContactIdKey = "c";
    private const string SafeIdKey = "sa";
    private const string SiteLocationCode = "s";

    public CallerInfoManager(IContactContextManager contactContextManager)
    {
        _contactContextManager = contactContextManager;
    }

    public CallerInfo GetFrom(HttpRequest request)
    {
        return ExtractCallerInfo(request.QueryString);
    }

    public CallerInfo GetFromHttpContext()
    {
        return GetFrom(HttpContext.Current.Request);
    }

客戶經理

   public class AccountsManager : IAccountsManager
{
    private readonly IAccountRepository _accountRepository;

    public AccountsManager(IAccountRepository accountRepository)
    {
        _accountRepository = accountRepository;
    }

    public List<Account> GetAll(string siteLocationCode)
    {
        return _accountRepository.GetAll(siteLocationCode);
    }

    public List<Account> GetAllWithNameContaining(string term, string siteLocationCode)
    {
        return _accountRepository.Search(term, siteLocationCode);
    }

    public Account Add(Account account)
    {
        _accountRepository.Add(account);
        return account;
    }
}

到目前為止,這是我對單元測試的了解。 我真的不認為我做得對。 我覺得我沒有適當地嘲笑對象。

問題:我應該在控制器內模擬和測試哪些方法?


我的測試:(第一個通過,第二個不起作用)

    [TestFixture]

公共類AccountControllerTests {

    //Tests that all accounts where returned
    [Test]
    public void GetAllAccounts_ReturnAllAccounts()
    {
        //Arrange
        var mockAccountsManager = A.Fake<IAccountsManager>();
        var mockCallerInfoManager = A.Fake<ICallerInfoManager>();

        using (var accountsController = new AccountController(mockAccountsManager, mockCallerInfoManager))
        {
            //Act
           List<Account> accounts = accountsController.Get();

            //Assert
           A.CallTo(() => mockCallerInfoManager.GetFromHttpContext()).MustHaveHappened();
           Assert.AreNotEqual(null, accounts); 
        }
    }

    //Tests that the proper search parameter was returned
    [Test]
    public void SearchforAccount_ReturnSearchAccount()
    {
        //Arrange
        var mockAccountsManager = A.Fake<IAccountsManager>();
        var mockCallerInfoManager = A.Fake<ICallerInfoManager>();

        Account searchAccountEntity = new Account
        {
            Id = 01,
            CompanyName = "google"

        };

        //Define search parameter
        AccountRequest mockAccountRequest = new AccountRequest
        {
            SearchTerm = "google"
        };

        using (var accountsController = new AccountController(mockAccountsManager, mockCallerInfoManager))
        {
            //Act
            List<Account> returnedAccounts = accountsController.Search(mockAccountRequest);
            mockAccountsManager.GetAllWithNameContaining("universal", "test");

            //Assert
            Assert.AreSame(mockAccountRequest, returnedAccounts);

        }
    }

問題:我應該在控制器內模擬和測試哪些方法?

這可能是為您設置任務的經理/團隊負責人/架構師/高級開發人員的問題:-)

第二個不工作

在我看來,這個實例是AccountController.Search但您不是在嘲笑_accountsManager.GetAllWithNameContaining

同樣與Assert.AreSame(mockAccountRequest, returnedAccounts); 一個是列表,另一個是AccountRequest

嘗試這個:

    [Test]
    public void SearchforAccount_ReturnSearchAccount()
    {
        //Arrange
        var mockAccountsManager = A.Fake<IAccountsManager>();
        var mockCallerInfoManager = A.Fake<ICallerInfoManager>();
        const string SearchTerm = "google"; // Use the passed in parameter in the CallTo setup

        //Define search parameter
        AccountRequest mockAccountRequest = new AccountRequest
        {
            SearchTerm = SearchTerm
        };

        List<Account> expected = new List<Account> { new Account() }; // What we expect to get back

        A.CallTo(() => mockAccountsManager.GetAllWithNameContaining(SearchTerm, A<string>.Ignored)).Returns(expected); // mock the call made in the controller

        using (var accountsController = new AccountController2(mockAccountsManager, mockCallerInfoManager))
        {
            //Act
            List<Account> returnedAccounts = accountsController.Search(mockAccountRequest);

            //Assert
            Assert.AreSame(expected, returnedAccounts);
        }
    }

我需要模擬HttpContext嗎?

為了使該測試正常進行,沒有。 ICallerInfoManager接口包裝了對HttpContext的調用並將其與控制器隔離,因此它將安全地運行,而無需訪問HttpContext

就是說,如果您需要測試所有內容,那就可以。 您要測試的代碼的麻煩部分將是:

public CallerInfo GetFrom(HttpRequest request)
{
    return ExtractCallerInfo(request.QueryString);
}

public CallerInfo GetFromHttpContext()
{
    return GetFrom(HttpContext.Current.Request);
}

由於對HttpContext的嚴格依賴。

HttpContextHttpRequest並不是可模擬的,但是有着密切的關系。 正如@Steve G在評論中提到的那樣,這是一個很大的話題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM