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

时间:2014-11-19 22:46:54

标签: c# asp.net-mvc-4 unit-testing moq

我是使用Moq的新手。我试图让这个单元测试工作,但我的对象似乎继续返回null。我在网上看到Setup()必须与实际调用匹配。我显然没有得到它,因为它仍然没有工作;它似乎与我匹配。这是我的代码示例。

测试项目的测试方法:

    [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));
    }

这是来自我的控制器的方法:

    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();
        }
    }

控制器中返回null的部分是

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

响应对象为null,因此在下一个语句中检查成功时,将抛出异常。有没有人知道我的设置/返回可能导致的问题?

感谢!!!!

2 个答案:

答案 0 :(得分:1)

在您的控制器中,您正在将participant.DoNotSendCuRewardsEmails更改为合同对象中的值,该值在您的设置中为false。您将方法设置为对于该参数为true,因为这是调用setup时参与者中包含的值。 Moq获取属性的值,就像调用setup时一样,它不会延迟评估对象属性。

答案 1 :(得分:0)

设置模拟时,必须使用input

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

它需要匹配您在控制器内进行的特定呼叫。