【问题标题】:How to create unit test project for wcf rest service in Visual Studio 2010 with mocking(open source)如何在 Visual Studio 2010 中使用 mocking(开源)为 wcf rest 服务创建单元测试项目
【发布时间】:2014-06-17 04:09:31
【问题描述】:

我们已经创建了 wcf rest 服务,根据客户的新要求,我们需要为所有服务方法创建单元测试用例。

我完成了研发,发现可以使用一些模拟来完成单元测试。

有人可以用 Visual Studio 2010 中的示例解释一下模拟(开源)。以便我们可以参考并创建相同的单元测试项目。

非常感谢。

以下是我创建帐户的代码,我想使用模拟测试此方法。

    [OperationContract]
    [WebInvoke(UriTemplate = "CreateAccount", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
    public CreateAccountServiceResponse CreateAccount(AuthenticateApplication Application, ApplicationCustomer Customer, CustomerService Service, Option Options)
    {
        Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new CustomExceptionDebug("CreateAccount?ApplicationID=" + Application.ApplicationID + "&UserName=" + Application.UserName + "&Password=" + Application.Password + "&FirstName=" + Customer.FirstName + "&LastName=" + Customer.LastName + "&Email=" + Customer.Email + "&CountryISO3=" + Customer.CountryISO3 + "&ServiceType=" + Service.Type + "&Amount=" + Service.Amount + "&CountryISO3=" + Customer.CountryISO3 + "&Telephone=" + Customer.Telephone), null));

        DataAccess.ServiceType objService = new DataAccess.ServiceType();
        ReloadServiceRepository objReload = new ReloadServiceRepository();
        #region Check Authentication of application and user
        int UserId = 0;

        if (!objReload.AuthenticateApplicationUser(Application, out UserId))
        {
            return new CreateAccountServiceResponse { ResultCode = ((int)ServiceResultCode.Error).ToString(), Message = ServiceMessage.InValidUser };
        }
        else
        {
            //objService = objReload.GetServiceTypeData(Application.ApplicationID, Customer.ServiceType);
            objService = objReload.GetServiceTypeData(Application.ApplicationID, Service.Type);
        }
        #endregion

        IAccountRepository _accountRepository = new AccountRepository();
        IBillingRepository _billingRepository = new BillingRepository();
        string sPIN = "";
        string sUniqueUserId = "";
        string sPassword = "";

        try
        {

            // Check if email already exists or not
            // if email already exists then call ReloadUsingPin and send back the response accordingly
            CCRAccount objectCCRAccount = _accountRepository.GetAccountFromEmail(Customer.Email);
            if (objectCCRAccount != null)
            {
                Customer.Account = objectCCRAccount.Account;
                var response = ReloadUsingPIN(Application, Customer, Service, Options);
                if (response != null)
                {
                    return new CreateAccountServiceResponse { ResultCode = response.ResultCode, Message = response.Message, PIN = Customer.Account, ResponseMessage = response.ResponseMessage };
                }
            }

            string sSpecifiedAccount = "", sAgent = "";
            string sMinutes = string.Empty;
            string amount = "";
            sSpecifiedAccount = Customer.Account;// THIS MAY CHANGE IF IT IS FOUND THAT THE EMAIL ALREADY EXISTS
            //Check for Amount passed in param or get from database
            if (objService != null)
            {
                if (objService.Amount != null)
                {
                    amount = objService.Amount.ToString();
                }
            }
            if (amount == string.Empty)
            {
                amount = Service.Amount;
            }

            LMCreditMinute lMinutes = null;
            if (Service.DestinationCountryCode != null)
            {
                lMinutes = _accountRepository.GetCountryInfoByCountryCode(Service.DestinationCountryCode);
                if (lMinutes != null)
                {
                    sMinutes = Convert.ToString(lMinutes.Minutes);
                }
            }



            //' CREATE OR CREDIT ACCOUNT


            while (sUniqueUserId != "*")
            {
                sUniqueUserId = CustomMethods.GeneratePin();
                if (_accountRepository.CheckUniqueUserId(sUniqueUserId))
                {
                    break;
                }
            }

            var rsAgent = _accountRepository.ExecuteProcedure(Customer.Email);
            if (rsAgent.Rows.Count > 0)
            {
                try
                {
                    sAgent = rsAgent.Rows[0]["Agent"].ToString();
                }
                catch (Exception ex)
                {
                    sAgent = rsAgent.Rows[0][0].ToString();
                }
            }
            var pass = CustomMethods.GeneratePin();
            sPassword = Customer.FirstName;
            if (Customer.FirstName.Length >= 3)
            {
                sPassword = sPassword.Substring(0, 3);
                sPassword = sPassword + pass.Substring(0, 3);
            }
            else
            {
                sPassword = pass.Substring(0, 6);
            }

            #region Save in Accounts table
            Account objAccount = new Account();
            objAccount.ACCOUNT1 = sPIN;
            objAccount.ENABLE = "X";
            objAccount.CONTACT = Customer.FirstName;
            objAccount.SALES_REP = string.Empty;
            objAccount.SALES_REP3 = (objService != null) ? objService.Sales_Rep3 ?? string.Empty : string.Empty;
            objAccount.ACCOUNT_GROUP = "WEBCC";
            objAccount.OPTIONS = "NB";
            objAccount.CALLBACK_NUMBER = "NCC";
            objAccount.RATE = "RATE";
            objAccount.EXPIRES = DateTime.Now.AddYears(1);
            objAccount.PREPAID = "X";
            if (objService != null)
            {
                if (objService.Starting_Credit != null)
                {
                    objAccount.STARTING_CREDIT = Convert.ToDouble(objService.Starting_Credit);
                }
                if (objService.Credit_Limit != null)
                {
                    objAccount.CREDIT_LIMIT = Convert.ToDouble(objService.Credit_Limit);
                }
                if (objService.Credit != null)
                {
                    objAccount.CREDIT = Convert.ToDouble(objService.Credit);
                }
            }
            _accountRepository.Add(objAccount);
            #endregion

            string body = "An account has been credited (" + sPIN + ") for ****** customer " + Customer.FirstName + " " + Customer.LastName + ".";

            #region Send email
            if (Options.SendEmail)
            {
                MailHelper.SendMail(ConfigurationManager.AppSettings["ReloadServiceMail"].ToString(), "", "", "Account Credited", true, body, null);

                EmailTemplate emailtemplate = _accountRepository.GetTemplate((int)EmailTemplateType.MinutesAdded);
                body = string.Empty;

                body = emailtemplate.Body;
                body = body.Replace("{{FN}}", Customer.FirstName); //-- Replace URL tag from Template
                body = body.Replace("{{USERNAME}}", sAgent); //-- Replace FirstName tag from Template
                body = body.Replace("{{IMG}}", ConfigurationManager.AppSettings["HostImgsURL"]);
                body = body.Replace("{{PWD}}", sPassword);
                body = body.Replace("{{MINUTES}}", sMinutes);
                body = body.Replace("{{COUNTRY}}", (lMinutes == null ? string.Empty : lMinutes.CountryName ?? string.Empty));
                MailHelper.SendMail(Customer.Email, "", "", emailtemplate.Subject.Replace("{{MINUTES}}", sMinutes), true, body, null);
            }
            #endregion

            return new CreateAccountServiceResponse { ResultCode = ((int)ServiceResultCode.Success).ToString(), Message = ServiceMessage.AccountCreated, ResponseMessage = sUniqueUserId + "~~~" + sAgent, PIN = sPIN };

        }
        catch (Exception ex)
        {
            Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new CustomExceptionDebug("CreateAccount: Message=" + ex.Message + "&InnerException" + ex.InnerException), null));
            return new CreateAccountServiceResponse { ResultCode = ((int)ServiceResultCode.Error).ToString(), Message = ServiceMessage.Error101, ResponseMessage = ex.Message };
        }
    }

【问题讨论】:

  • 你到底想测试什么?如果您只想在 VS 中使用模拟单元测试任何示例,只需 Google。你会找到足够的。就我个人而言,我喜欢将 NUnit 用于测试、NSubstitute 用于模拟和 ReSharper 用于运行测试的组合。 NUnit 和 NUsbstitute 是开源的,ReSharper 不是。
  • 我在内置测试项目中使用 VS 2010。我有一个查询:假设我正在为“CreateAccount”功能创建测试方法,在这种情况下,是否会创建新用户或模拟会阻止它执行,如果是,如何实现?请建议
  • 模拟(或者在这种情况下:“存根”)的重点是避免在某些数据库中创建真实帐户。因此,如果您想对您的服务进行单元测试,您将 mock 它用于数据访问的任何类,例如一个存储库。如果您可以发布您的服务类的代码,我可以尝试给您举个例子。
  • 感谢您提供信息,我在问题描述中添加了代码。请看一看。谢谢
  • 我们可能需要跳过这个方法 "_accountRepository.Add(objAccount);"因此不应创建该帐户。使用 MOQ dll,因为我使用的是相同的。

标签: visual-studio-2010 unit-testing


【解决方案1】:

您将很难按原样测试此方法。事实上,我建议在将其应用于此代码之前了解更多关于单元测试和dependency injection 的信息,除非您有时间和动力直接跳入并从痛苦的错误中吸取教训(就像我开始进行单元测试时所做的那样) .

在我看来,您的代码存在两个最严重的问题:

  • 该方法很长,并且做了很多不同的事情。代码越短,测试就越容易。尝试将单独的关注点重构到它们自己的类中(例如,最后的电子邮件发送代码)。然后,您可以在当前方法的测试中模拟它们,并单独测试电子邮件发送的内容。
  • 此时您几乎无法模拟任何内容,因为该方法会自行创建其所有协作者。为了模拟任何东西,你必须能够注入它。例如,您可以将其作为参数传递,而不是创建 ReloadServiceRepository。然后你就可以在你的测试中通过一个模拟,它的行为与你之前“告诉”他的完全一样。

如果你想了解更多,我可以推荐这些书:

花时间学习一些基础知识,你会更快地编写出更好的测试。

【讨论】:

    猜你喜欢
    • 2011-03-26
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多