AuthorizeNet/sdk-dotnet

View on GitHub
AuthorizeNETtest/Api/Controllers/Test/ApiCoreTestBase.cs

Summary

Maintainability
F
3 days
Test Coverage
using AuthorizeNet.Utility;

namespace AuthorizeNet.Api.Controllers.Test
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using AuthorizeNet.Api.Contracts.V1;
    using AuthorizeNet.Api.Controllers.Bases;
    using AuthorizeNet.Test;
    using AuthorizeNet.Util;
    using NUnit.Framework;
    using NMock;

    // ReSharper disable FieldCanBeMadeReadOnly.Local
    // ReSharper disable NotAccessedField.Local
#pragma warning disable 169
#pragma warning disable 649
    [TestFixture]
    public abstract class ApiCoreTestBase {

        protected static readonly Log Logger = LogFactory.getLog(typeof(ApiCoreTestBase));
    
        protected static readonly IDictionary<String, String> ErrorMessages ;

        protected static AuthorizeNet.Environment TestEnvironment = AuthorizeNet.Environment.SANDBOX;
        //protected static AuthorizeNet.Environment TestEnvironment = AuthorizeNet.Environment.HOSTED_VM;
        
        static readonly String ApiLoginIdKey ;
        static readonly String TransactionKey ;
        static String _md5HashKey ;
    
        DateTime _pastDate;
        DateTime _nowDate;
        DateTime _futureDate;
        String _nowString ;
        DateTime _now = DateTime.UtcNow;

        protected string RefId ;
        protected int Counter;
        protected String CounterStr;

        protected merchantAuthenticationType CustomMerchantAuthenticationType;

        protected ARBSubscriptionType ArbSubscriptionOne;

        //protected ARBSubscriptionType ArbSubscriptionTwo;
        protected bankAccountType BankAccountOne;
        protected creditCardTrackType TrackDataOne;
        protected creditCardType CreditCardOne;
        protected customerAddressType CustomerAddressOne;
        protected customerDataType CustomerDataOne;
        protected customerPaymentProfileType CustomerPaymentProfileOne;
        protected customerProfileType CustomerProfileType;
        protected customerType CustomerOne;
        protected customerType CustomerTwo;
        protected driversLicenseType DriversLicenseOne; 
        protected encryptedTrackDataType EncryptedTrackDataOne;
        protected nameAndAddressType NameAndAddressTypeOne;
        protected nameAndAddressType NameAndAddressTypeTwo;
        protected orderType OrderType;
        protected paymentScheduleType PaymentScheduleTypeOne;
        protected paymentType PaymentOne;
        protected payPalType PayPalOne;

        protected MockFactory MockContext = null;
        private readonly AnetRandom _random = new AnetRandom();
        static ApiCoreTestBase() {

            //now we support Tls only, and .net defaults to TLS
            //System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12;

            var config = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.None);
            Logger.error(String.Format("Configuration file used: {0}, Exists:{1}", config.FilePath, config.HasFile));

            //getPropertyFromNames get the value from properties file or environment
            ApiLoginIdKey = UnitTestData.GetPropertyFromNames(AuthorizeNet.Util.Constants.EnvApiLoginid, AuthorizeNet.Util.Constants.PropApiLoginid);
            TransactionKey = UnitTestData.GetPropertyFromNames(AuthorizeNet.Util.Constants.EnvTransactionKey, AuthorizeNet.Util.Constants.PropTransactionKey);
            _md5HashKey = UnitTestData.GetPropertyFromNames(AuthorizeNet.Util.Constants.EnvMd5Hashkey, AuthorizeNet.Util.Constants.PropMd5Hashkey);

            //require only one cnp or cp merchant keys
            if (null != ApiLoginIdKey && null != TransactionKey)
            {
                Logger.debug("Merchant Login and transaction keys are present.");
            }
            else
            {
                throw new ArgumentException(
                    "LoginId and/or TransactionKey have not been set. Merchant keys are required.");
            }

            ErrorMessages = new Dictionary<string, string>();
        }

        [TestFixtureSetUp]
        public static void SetUpBeforeClass()//TestContext context)
        {
            ErrorMessages.Clear();
            ErrorMessages.Add("E00003", "");   //The message is dynamic based on the xsd violation.
            ErrorMessages.Add("E00007", "User authentication failed due to invalid authentication values.");
            ErrorMessages.Add("E00027", "");
            ErrorMessages.Add("E00040", "");
            ErrorMessages.Add("E00090", "PaymentProfile cannot be sent with payment data." );
            ErrorMessages.Add("E00091", "PaymentProfileId cannot be sent with payment data.");        
            ErrorMessages.Add("E00092", "ShippingProfileId cannot be sent with ShipTo data.");        
            ErrorMessages.Add("E00093", "PaymentProfile cannot be sent with billing data.");        
            ErrorMessages.Add("E00095", "ShippingProfileId is not provided within Customer Profile.");
        }

        [TestFixtureTearDown]
        public static void TearDownAfterClass()
        {
        }

        public static String DateFormat = "yyyy-MM-dd'T'HH:mm:ss";

        [SetUp]
        public void SetUp()
        {
            MockContext = new MockFactory();

            //initialize counter
            Counter = _random.Next(1, (int) (Math.Pow(2, 24)));
            CounterStr = GetRandomString("");

            _now = DateTime.UtcNow;
            _nowString = _now.ToString(DateFormat);

            _pastDate = _now.AddMonths(-1);
            _nowDate = _now;
            _futureDate = _now.AddMonths(1);

            CustomMerchantAuthenticationType = new merchantAuthenticationType
                {
                    name = ApiLoginIdKey,
                    ItemElementName = ItemChoiceType.transactionKey,
                    Item = TransactionKey,
                };

            //        merchantAuthenticationType.setSessionToken(GetRandomString("SessionToken"));
            //        merchantAuthenticationType.setPass_word(GetRandomString("Pass_word"));
            //        merchantAuthenticationType.setMobileDeviceId(GetRandomString("MobileDevice"));

            //        ImpersonationAuthenticationType impersonationAuthenticationType = new ImpersonationAuthenticationType();
            //        impersonationAuthenticationType.setPartnerLoginId(CnpApiLoginIdKey);
            //        impersonationAuthenticationType.setPartnerTransactionKey(CnpTransactionKey);
            //        merchantAuthenticationType.setImpersonationAuthentication(impersonationAuthenticationType);

            CustomerProfileType = new customerProfileType
                {
                    merchantCustomerId = GetRandomString("Customer"),
                    description = GetRandomString("CustomerDescription"),
                    email = CounterStr + ".customerProfileType@test.anet.net",
                };

            //make sure these elements are initialized by calling get as it uses lazy initialization
            var paymentProfiles = CustomerProfileType.paymentProfiles;
            var addresses = CustomerProfileType.shipToList;

            CreditCardOne = new creditCardType
                {
                    cardNumber = "4111111111111111",
                    expirationDate = "2038-12",
                };
            //        creditCardOne.setCardCode("");

            BankAccountOne = new bankAccountType
                {
                    accountType = bankAccountTypeEnum.savings,
                    routingNumber = "125000000",
                    accountNumber = GetRandomString("A/C#"),
                    nameOnAccount = GetRandomString("A/CName"),
                    echeckType = echeckTypeEnum.WEB,
                    bankName = GetRandomString("Bank"),
                    checkNumber = CounterStr,
                };

            TrackDataOne = new creditCardTrackType
                {
                    ItemElementName = ItemChoiceType1.track1,
                    Item = GetRandomString("Track1"),
                    //trackDataOne.setTrack2(GetRandomString("Track2"));
                };

            EncryptedTrackDataOne = new encryptedTrackDataType
                {
                    FormOfPayment = new KeyBlock(),
                };
            //keyBlock.setValue(value);

            PayPalOne = new payPalType
                {
                    successUrl = GetRandomString("https://success.anet.net"),
                    cancelUrl = GetRandomString("https://cancel.anet.net"),
                    paypalLc = GetRandomString("Lc"),
                    paypalHdrImg = GetRandomString("Hdr"),
                    paypalPayflowcolor = GetRandomString("flowClr"),
                    payerID = GetRandomString("PayerId"),
                };

            PaymentOne = new paymentType
                {
                    Item = CreditCardOne
                };
            //paymentOne.setBankAccount(bankAccountOne);
            //paymentOne.setTrackData(trackDataOne);
            //paymentOne.setEncryptedTrackData(encryptedTrackDataOne);
            //paymentOne.setPayPal( payPalOne);

            //        driversLicenseOne = new DriversLicenseType();
            //        driversLicenseOne.setNumber(GetRandomString("DLNumber"));
            //        driversLicenseOne.setState(GetRandomString("WA"));
            //        driversLicenseOne.setDateOfBirth(nowString);

            CustomerAddressOne = new customerAddressType
                {
                    firstName = GetRandomString("FName"),
                    lastName = GetRandomString("LName"),
                    company = GetRandomString("Company"),
                    address = GetRandomString("StreetAdd"),
                    city = "Bellevue",
                    state = "WA",
                    zip = "98000",
                    country = "USA",
                    phoneNumber = FormatToPhone(Counter),
                    faxNumber = FormatToPhone(Counter + 1),
                };

            CustomerPaymentProfileOne = new customerPaymentProfileType
                {
                    customerType = customerTypeEnum.individual,
                    payment = PaymentOne,
                };
            //        customerPaymentProfileOne.setBillTo(customerAddressOne);
            //        customerPaymentProfileOne.setDriversLicense(driversLicenseOne);
            //        customerPaymentProfileOne.setTaxId(GetRandomString("XX"));


            CustomerOne = new customerType
                {
                    type = customerTypeEnum.individual,
                    id = GetRandomString("Id"),
                    email = CounterStr + ".customerOne@test.anet.net",
                    phoneNumber = FormatToPhone(Counter),
                    faxNumber = FormatToPhone(Counter + 1),
                    driversLicense = DriversLicenseOne,
                    taxId = "911011011",
                };

            CustomerTwo = new customerType();

            var interval = new paymentScheduleTypeInterval
                {
                    length = 1,
                    unit = ARBSubscriptionUnitEnum.months,
                };

            OrderType = new orderType()
                {
                    //TODO ADD VALIDATION ON INVOICE LENGTH
                    invoiceNumber = GetRandomString("Inv:"),
                    description = GetRandomString("Description"),
                };

            NameAndAddressTypeOne = new nameAndAddressType
                {
                    firstName = GetRandomString("FName"),
                    lastName = GetRandomString("LName"),
                    company = GetRandomString("Company"),
                    address = GetRandomString("Address"),
                    city = GetRandomString("City"),
                    state = GetRandomString("State"),
                    zip = "98004",
                    country = "USA",
                };

            NameAndAddressTypeTwo = new nameAndAddressType
                {
                    firstName = GetRandomString("FName"),
                    lastName = GetRandomString("LName"),
                    company = GetRandomString("Company"),
                    address = GetRandomString("Address"),
                    city = GetRandomString("City"),
                    state = GetRandomString("State"),
                    zip = "98004",
                    country = "USA",
                };

            PaymentScheduleTypeOne = new paymentScheduleType
                {
                    interval = interval,
                    startDate = _nowDate,
                    totalOccurrences = 5,
                    trialOccurrences = 0, 
                };

            ArbSubscriptionOne = new ARBSubscriptionType
                {
                    amount = SetValidSubscriptionAmount(Counter),
                    billTo = NameAndAddressTypeOne,
                    customer = CustomerOne,
                    name = GetRandomString("Name"),
                    order = OrderType,
                    payment = PaymentOne,
                    paymentSchedule = PaymentScheduleTypeOne,
                    shipTo = NameAndAddressTypeOne,
                    trialAmount= SetValidSubscriptionAmount(0),
                };

            CustomerDataOne = new customerDataType
                {
                    driversLicense = CustomerOne.driversLicense,
                    email = CustomerOne.email,
                    id = CustomerOne.id,
                    taxId = CustomerOne.taxId,
                    type = CustomerOne.type,
                };
        
            RefId = CounterStr;
        }

        [TearDown]
        public void TearDown() {
            MockContext.VerifyAllExpectationsHaveBeenMet();
        }

        string GetRandomString(string title) {
            return String.Format("{0}{1}", title, Counter);
        }
    
        public String FormatToPhone(int number) {
            var formattedNumber = string.Format( "{0:0000000000}", number);
            return     formattedNumber.Substring(0, 3)+"-"+
                    formattedNumber.Substring(3, 3)+"-"+
                    formattedNumber.Substring(6, 4);
        }

        public decimal SetValidTaxAmount(decimal amount)
        {
            return (amount * TaxRate);
        }

        public decimal SetValidTransactionAmount(int number)
        {
            //updated to return a value with dollars and cents and not just whole dollars.
            return (Decimal)setValidAmount(number, MaxTransactionAmount/100);
        }

        public decimal SetValidSubscriptionAmount(int number)
        {
            return setValidAmount(number, MaxSubscriptionAmount);
        }
    
        private decimal setValidAmount(int number, int maxAmount)
        {
            //Test that result is not larger than the specified max value
            number = (number > maxAmount) ? (number % maxAmount) : number;

            Decimal dollarsAndCents = (decimal)number / 100;

            //Test that result is not less than the global Min Value
            return dollarsAndCents = (dollarsAndCents < MinAmount) ? (MinAmount + dollarsAndCents) : dollarsAndCents;
        }

        static ANetApiResponse _errorResponse;

        protected ANetApiResponse GetErrorResponse() {
            return _errorResponse;
        }

        private const int MaxSubscriptionAmount = 1000; //214747;
        private const int MaxTransactionAmount = 10000; //214747;
        private const int MinAmount = 1;
        private const decimal TaxRate = 0.10m;

        protected static TS ExecuteTestRequestWithSuccess<TQ, TS, TT>(TQ request, AuthorizeNet.Environment execEnvironment = null)
            where TQ : ANetApiRequest
            where TS : ANetApiResponse
            where TT : ApiOperationBase<TQ, TS> 
        {
            TS response = ExecuteTestRequest<TQ, TS, TT>( true, request, execEnvironment);
        
            return response;
        }

        protected static TS ExecuteTestRequestWithFailure<TQ, TS, TT>(TQ request, AuthorizeNet.Environment execEnvironment = null)
            where TQ : ANetApiRequest
            where TS : ANetApiResponse
            where TT : ApiOperationBase<TQ, TS> 
        {
            TS response = ExecuteTestRequest<TQ, TS, TT>(false, request, execEnvironment);
        
            return response;
        }

        private static TS ExecuteTestRequest<TQ, TS, TT>(bool successExpected, TQ request, AuthorizeNet.Environment execEnvironment = null) 
            where TQ : ANetApiRequest
            where TS : ANetApiResponse
            where TT : ApiOperationBase<TQ, TS> 
        {

            LogHelper.debug( Logger, "Created {0} Request: '{1}'", request.GetType(), request);
        
            TS response = null;
            TT controller = null;
            _errorResponse = null;        
            var controllerClass = typeof (TT);
            try {
                var parameters = new object[] {request} ;
                var controllerObject = Activator.CreateInstance(controllerClass, parameters);
                if ( controllerObject is TT)
                {
                    controller = (TT) controllerObject;
                }
                if (null != controller)
                {
                    ANetApiResponse baseResponse = controller.ExecuteWithApiResponse(execEnvironment);
                    LogHelper.info(Logger, "{0} ResultCode: {1}", controllerClass, controller.GetResultCode());
                    LogHelper.info(Logger, "{0} Results:    {1}", controllerClass, controller.GetResults());
                    response = (TS) baseResponse;
                }
                else
                {
                    LogHelper.error(Logger, "Unable to instantiate Controller: '{0}'", controllerClass);
                }
            } catch (Exception e) {
                LogHelper.error(Logger, "Exception : '{0}' during {1}", e.Message, controllerClass);
            }
            if ( successExpected)
            {
                ProcessFailureResult<TQ, TS, TT>( true, controller, response);        
                ValidateSuccess<TQ, TS, TT>( controller, response);
            } else {
                ValidateFailure<TQ, TS, TT>( controller, response);
            }
            if (null == response && null != controller && null != controller.GetErrorResponse())
            {
                _errorResponse = controller.GetErrorResponse();
            }
        
            return response;
        }

        protected static void ProcessFailureResult<TQ, TS, TT>(bool fail, TT controller, TS response) 
            where TQ : ANetApiRequest
            where TS : ANetApiResponse
            where TT : ApiOperationBase<TQ, TS> 
        {
            //in case there are errors, log the error messages
            if ( messageTypeEnum.Ok != controller.GetResultCode())
            {
                foreach ( var aMessage in controller.GetResults()) {
                    LogHelper.info(Logger, "Controller Messages: '{0}' ", aMessage);
                }
                DisplayResponse(response, "Failure Messsages");
                var errorResponse = controller.GetErrorResponse();
                DisplayResponse(errorResponse, "Error Response Messages");
                if ( fail)
                {
                    Assert.Fail("Request failed.");
                }
            }
        }

        protected static void ValidateSuccess<TQ, TS, TT>( TT controller, TS response)
            where TQ : ANetApiRequest
            where TS : ANetApiResponse
            where TT : ApiOperationBase<TQ, TS> 
        {
            Assert.AreEqual( messageTypeEnum.Ok, controller.GetResultCode());
            Assert.IsNull(controller.GetErrorResponse());
            Assert.IsNotNull(response);
            DisplayResponse( response, "Success Messages");
        }

        protected static void ValidateFailure<TQ, TS, TT>( TT controller, TS response)
            where TQ : ANetApiRequest
            where TS : ANetApiResponse
            where TT : ApiOperationBase<TQ, TS> 
        {
            Assert.AreEqual( messageTypeEnum.Error, controller.GetResultCode());
            //TODO Until error response is fixed
            //Assert.assertNotNull(controller.getErrorResponse());
            //Assert.assertNull(response);
            ProcessFailureResult<TQ, TS, TT>(false, controller, response);
        }
    
        protected static void DisplayResponse(ANetApiResponse response, String source) {
            LogHelper.info(Logger, "Source '{0}' ", source);
            if (null != response) {
                var messageType = response.messages;
                if ( null != messageType) {
                    LogHelper.info(Logger, "MessageCode: '{0}' ", messageType.resultCode.ToString());
                    foreach ( var aMessage in messageType.message) {
                        LogHelper.info(Logger, "Message: '{0}':'{1}' ", aMessage.code, aMessage.text);
                    }
                }
            }
        }

        protected void ValidateErrorCode(messagesType messagesType, string errorCode)
        {
            var firstError = GetFirstErrorMessage( messagesType);
            if (null != firstError)
            {
                Assert.AreEqual( errorCode, firstError.code);
                if ( ErrorMessages.ContainsKey(errorCode))
                {
                    string message = ErrorMessages[errorCode];
                    if ( !(string.IsNullOrEmpty(message)))
                    {
                        Assert.AreEqual( message, firstError.text);
                    }
                }
            }
        }
    
        protected static string GetFirstErrorCode(messagesType messagesType)
        {
            var errorMessage = GetFirstErrorMessage( messagesType);
            return ( (null != errorMessage) ? errorMessage.code : null); 
        }

        protected static string GetFirstErrorText(messagesType messagesType)
        {
            var errorMessage = GetFirstErrorMessage( messagesType);
            return ( (null != errorMessage) ? errorMessage.text : null); 
        }
    
        protected static messagesTypeMessage GetFirstErrorMessage(messagesType messagesType)
        {
            messagesTypeMessage errorMessage = null;
            if (  null != messagesType.message)
            {
                foreach( var aMessage in messagesType.message)
                {
                    errorMessage = aMessage;
                    break;
                }
            }
        
            return errorMessage;
        
        }

        protected void SetMockControllerExpectations<TQ, TS, TT> (
            IApiOperation<TQ, TS> mockController,
            TQ mockRequest,
            TS mockResponse,
            ANetApiResponse errorResponse, 
            List<String> results,
            messageTypeEnum messageType)
            where TQ : ANetApiRequest
            where TS : ANetApiResponse
            where TT : IApiOperation<TQ, TS>
        {
            var mockEnvironment = AuthorizeNet.Environment.CUSTOM;

            //using (MockContext.Unordered())
            {
                //Expect.On(mockController).Any.Method(i => i.Execute(mockEnvironment));
                Expect.On(mockController).Any.Method(i => i.Execute(mockEnvironment)).With(mockEnvironment);
                Expect.On(mockController).Any.Method(i => i.GetApiResponse()).WillReturn(mockResponse);
                //Expect.On(mockController).Between(0, 10).Method(i => i.ExecuteWithApiResponse(mockEnvironment)).WillReturn(mockResponse);
                Expect.On(mockController).Any.Method(i => i.ExecuteWithApiResponse(mockEnvironment)).With(mockEnvironment).WillReturn(mockResponse);
                Expect.On(mockController).Any.Method(i => i.GetResults()).WillReturn(results);
                Expect.On(mockController).Any.Method(i => i.GetResultCode()).WillReturn(messageType);
                Expect.On(mockController).Any.Method(i => i.GetErrorResponse()).WillReturn(errorResponse);
            }

            if (null != mockRequest && null != mockResponse)
            {
                mockResponse.refId = mockRequest.refId;
            }
            var realController = Activator.CreateInstance(typeof(TT), mockRequest);
            Assert.IsNotNull(realController);

            LogHelper.info(Logger, "Request: {0}", mockRequest);
            ShowProperties(mockRequest);
            LogHelper.info(Logger, "Response: {0}", mockResponse);
            ShowProperties(mockResponse);
        }

        protected Mock<IApiOperation<TQ,TS>> GetMockController<TQ, TS>()  where TQ : ANetApiRequest where TS : ANetApiResponse
        {
            return MockContext.CreateMock<IApiOperation<TQ, TS>>();
        }

        public static void ShowProperties(Object bean) {  
            if ( null == bean) { return; }

            try
            {
                var fieldInfos = bean.GetType().GetFields();//BindingFlags.GetProperty);
                foreach (var pd in fieldInfos)
                {
                    var name = pd.Name;
                    var type = pd.FieldType;
 
                    if (!("class".Equals(name)) &&
                        !(bean.ToString().Equals(name)))
                    {
                        try
                        {
                            var value = pd.GetValue(bean);
                            //var value = bean.GetType().GetField(name).GetValue(bean);
                            LogHelper.info(Logger, "Field Type: '{0}', Name:'{1}', Value:'{2}'", type, name, value);
                            ProcessCollections(type, name, value);
                            //process compositions of custom classes
                            //if (null != value && 0 <= type.ToString().IndexOf("AuthorizeNet.", System.StringComparison.Ordinal))

                            var whiteListAssembly = (type.Assembly.FullName.IndexOf("AuthorizeNET", StringComparison.Ordinal) >= 0 );

                            if (null != value &&
                                whiteListAssembly &&
                                !(value is Enum) &&
                                !value.GetType().IsPrimitive &&
                                !(value is string))
                            {
                                ShowProperties(value);
                            }

                            var propertyChanged = bean as INotifyPropertyChanged;
                            if (propertyChanged != null)
                            {
                                var changed = false;
                                propertyChanged.PropertyChanged += (s, e) => { if (e.PropertyName == name) changed = true; };
                            }
                        } catch (Exception e) {
                            LogHelper.info(Logger, "Exception during getting Field value: Type: '{0}', Name:'{1}', Message: {2}, StackTrace: {3}", type, name, e.Message, e.StackTrace);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                LogHelper.info(Logger, "Exception during navigating properties: Message: {0}, StackTrace: {1}", e.Message, e.StackTrace);
            }  
        }

        public static void ProcessCollections( Type type, String name, Object value)
        {
            if (null == type) return;
            var values = value as IEnumerable;
            if (values != null &&
                !(value is string))
            {
                LogHelper.info(Logger, "Iterating on Collection: '{0}'", name);
                foreach (var aValue in values)
                {
                    ShowProperties(aValue);
                }
            }
        }

    }
#pragma warning restore 649
#pragma warning restore 169
// ReSharper restore NotAccessedField.Local
// ReSharper restore FieldCanBeMadeReadOnly.Local
}