简体   繁体   English

使用Moq进行单元测试,但对象返回Null

[英]Using Moq to unit test but the object returns Null

I'm new to using Moq. 我是使用Moq的新手。 I am trying to get this unit test to work but my object seems to keep returning null. 我正在尝试使此单元测试正常工作,但我的对象似乎一直返回null。 I saw online that the Setup() must match the actual call. 我在网上看到Setup()必须与实际调用匹配。 I'm obviously not getting it cause it still doesn't work; 我显然没有得到它,因为它仍然不起作用。 it seems to match to me. 它似乎与我匹配。 Here's my code samples. 这是我的代码示例。

Test method from test project: 测试项目的测试方法:

    [TestMethod]
    public void CanPutEmailOptOut()
    {
        var mockParticipant = new PscuParticipant
            {
                ParticipantId = 1,
                DoNotSendCuRewardsEmails = false,
                DoNotSendEarnBonusPointEmail = false,
                CardNumber = "VPZS5zXFUex2SJikkXFVrnvt2/R38yomFXwkslgXNKkgAFsjvt94p1h6J/XUEc6yQ5JzmT6+W8AdxuBSbp9e0SXAN60oHuZtWhAgGHhU+GaxJfCQHitc2+VBSZ/DxwW7Bpw="
            };

        MockBootstrapper.Instance.WithRepositoryData(new[] {mockParticipant});
        var input = new EmailOptOutContract
            {
                DoNotSendCuRewardsEmails = true,
                DoNotSendEarnBonusPointEmail = true
            };

        _affinityOptOutApiClient
            .Setup(
                x =>
                x.CallAffinityOptOutStatus(It.IsAny<string>(), 
                                           It.IsAny<string>(),
                                           mockParticipant.DoNotSendEarnBonusPointEmail,
                                           mockParticipant.ParticipantId))
            .Returns<HindaHttpResponse<OptOutResponse>>(x => new HindaHttpResponse<OptOutResponse>
                {
                    StatusCode = AffinityResultCode.Success,
                    ResponseObject = new OptOutResponse { MemberId = "999999999", Status = "success" }
                });

        var response = Controller.Put(mockParticipant.ParticipantId, input);

        var contract = response.ShouldBeSuccess<SuccessContract>();
        var participant = RepositoryFactory.CreateReadOnly<PscuParticipant>().FirstOrDefault(x => x.ParticipantId == mockParticipant.ParticipantId);
        Assert.AreEqual(input.DoNotSendCuRewardsEmails, participant.DoNotSendCuRewardsEmails);
        Assert.AreEqual(input.DoNotSendEarnBonusPointEmail, participant.DoNotSendEarnBonusPointEmail);
    }

    protected override void Configure()
    {
        MockBootstrapper.Override(config => config.For<IEncryptionService>().Use<EncryptionService>());
        _affinityOptOutApiClient = new Mock<IAffinityOptOutApiClient>(MockBehavior.Strict);
        MockBootstrapper.Override(config => config.For<IAffinityOptOutApiClient>().Use(_affinityOptOutApiClient.Object));
    }

Here's the method from my controller: 这是我的控制器中的方法:

    public HttpResponseMessage Put(int participantId, [FromBody]EmailOptOutContract contract)
    {
        if (contract == null)
            return Failure(ApiReturnCodes.InvalidRequestContract
                            , "Invalid Request Contract",
                            string.Format("Contract Is Null in controller method {0}", System.Reflection.MethodBase.GetCurrentMethod()),
                            HttpStatusCode.BadRequest);

        using (new UnitOfWorkScope())
        {
            var participant = GetParticipant(participantId);
            if (participant == null)
            {
                return NotFound(ApiReturnCodes.ParticipantNotFound, "Participant ID not found.");
            }

            participant.DoNotSendCuRewardsEmails = contract.DoNotSendCuRewardsEmails;
            participant.DoNotSendEarnBonusPointEmail = contract.DoNotSendEarnBonusPointEmail;

            string cardNumber = ServiceLocator.Current.GetInstance<IEncryptionService>().Decrypt(participant.CardNumber);
            cardNumber = AesEncrypt(cardNumber);

            string email = null;
            var partic = GetParticipantData(participant.ParticipantId);

            if (partic != null)
                email = partic.Email;

            HindaHttpResponse<OptOutResponse> response =
                _affinityOptOutApiClient.CallAffinityOptOutStatus(cardNumber, email, contract.DoNotSendEarnBonusPointEmail, participant.ParticipantId);

            if (response.StatusCode == AffinityResultCode.Success && response.ResponseObject.Status == "success")
                participant.AffinityMembId = response.ResponseObject.MemberId;
            else
                return BadRequest(ApiReturnCodes.AffinityInternalServerError, response.ExternalErrorMessage);

            return Ok();
        }
    }

The part that comes back null in the controller is 控制器中返回null的部分是

HindaHttpResponse<OptOutResponse> response =
                _affinityOptOutApiClient.CallAffinityOptOutStatus(cardNumber, email, contract.DoNotSendEarnBonusPointEmail, participant.ParticipantId);

The response object is null so when it is checked in the next statement for success, the exception is thrown. 响应对象为null,因此在下一条语句中检查它是否成功时,将引发异常。 Does anyone know what might be wrong with my Setup/Return that's causing problems? 有人知道我的设置/退货可能出了什么问题吗?

Thanks!!!! 谢谢!!!!

In your controller you're changing participant.DoNotSendCuRewardsEmails to the value in the contract object, which in your setup of that is false. 在您的控制器中,您正在将participant.DoNotSendCuRewardsEmails更改为合同对象中的值,在您的设置中该值为false。 You setup your method to expect true for that parameter as that is the value contained in participant when setup is called. 您将方法设置为期望对该参数为true,因为这是调用setup时参与者中包含的值。 Moq gets the value of the property as is when setup is called, it doesn't lazy evaluate the objects property. Moq会在调用安装程序时按原样获取属性的值,它不会偷懒地评估objects属性。

When you setup the mock, you have to use input 设置模拟时,必须使用input

x.CallAffinityOptOutStatus(
    It.IsAny<string>(), 
    It.IsAny<string>(),
    input.DoNotSendEarnBonusPointEmail,
    mockParticipant.ParticipantId)

It needs to match the specific call you are making inside the controller. 它需要匹配您在控制器内部进行的特定调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM