使用rhino mock进行lambda单元测试失败

时间:2010-12-02 17:49:30

标签: c# unit-testing lambda rhino-mocks

如果我有这个测试

Expect.Call(_session.Single<Admin>(x => x.Email == userModel.Email)).Repeat.Once().Return(null);

告诉我

  

Rhino.Mocks.Exceptions.ExpectationViolationException   :   ISession.Single(X   =&GT; (x.Email == value(Enquete.Test.Controllers.MemberControllerTest +&lt;&gt; c__DisplayClassb).userModel.Email));   预期#1,实际#0。

它失败但是如果我添加.IgnoreArguments()它就可以了。是否可以使用lambda进行测试?如果我调试我可以看到我的电子邮件是相同的。

这是完整的测试:

[Test]
        public void Register_Post_ReturnRedirectOnSuccess()
        {
            _builder.InitializeController(_controller);

            var userModel = TestHelper.CreateMemberModel();
            var returnMemberRole = "Member";
            var tempPassword = "Val1dPass";
            var member = TestHelper.CreateMember(userModel);
            var emailSubscription = "subscription@corpiq.com";
            var subjectNotification = "sujet du meessaaggee";
            var mailUseSSL = "true";
            var message = userModel.FirstName + " " + userModel.LastName + " s'est inscrit au système d'enquête en ligne, veuillez confirmer son inscription.";
            member.PasswordExpire = DateTime.Now.AddDays(-1);
            member.Phone = userModel.Phone;
            member.MemberNumber = userModel.MemberNumber;
            member.PasswordExpire = DateTime.Now.AddDays(-1);

            Expect.Call(_session.Single<Admin>(x => x.Email == userModel.Email)).Repeat.Once().Return(null);
            Expect.Call(_session.Single<Member>(x => x.Email == userModel.Email)).Repeat.Once().IgnoreArguments().Return(null);
            Expect.Call(_authService.GeneratePassword()).Repeat.Once().Return(tempPassword);
            Expect.Call(_authService.MemberRole).Repeat.Once().Return(returnMemberRole);
            Expect.Call(_authService.RegisterUser(userModel.Email, tempPassword, returnMemberRole)).Repeat.Once().Return(MembershipCreateStatus.Success);
            _session.Add(member);
            LastCall.Repeat.Once();
            _session.CommitChanges();
            LastCall.Repeat.Once();
            Expect.Call(_configHelper.GetValue("emailSubscription")).Repeat.Once().Return(emailSubscription);
            Expect.Call(_configHelper.GetValue("subjectNotification")).Repeat.Once().Return(subjectNotification);
            Expect.Call(_configHelper.GetValue("MailUseSSL")).Repeat.Once().Return(mailUseSSL);
            _mailHelper.SendMail(emailSubscription, subjectNotification, message, Convert.ToBoolean(mailUseSSL));
            LastCall.Repeat.Once();

            _mock.ReplayAll();
            var result = _controller.Register(userModel);

            _mock.VerifyAll();
            result.AssertActionRedirect().ToAction<MemberController>(c => c.RegisterSuccess());

        }

谢谢!

2 个答案:

答案 0 :(得分:1)

单元测试中的lambda编译为类级方法(单元测试中的方法)。在你的控制器中,一个不同的lambda编译成一个类级方法(在控制器内部)。使用了两种不同的方法,因此Rhino Mocks显示了期望误差。更多信息:http://groups.google.com/group/rhinomocks/browse_frm/thread/a33b165c16fc48ee?tvc=1

答案 1 :(得分:1)

不幸的是,C#中的lambdas使用引用相等,而不是值相等。请尝试以下方法:

Func<bool> f1 = () => true;
Func<bool> f2 = () => true;
Console.WriteLine("f1 == f2 results in " + (f1 == f2));
猜猜是什么?答案是假的。

表达式也是错误的......

Expression<Func<bool>> f1 = () => true;
Expression<Func<bool>> f2 = () => true;
Console.WriteLine(f1.ToString());          // Outputs "() => True"
Console.WriteLine("a1 == a2 results in " + (f1 == f2)); // False

不幸的是,在C#(以及Rhino Mocks)中解决这个问题(以及它的丑陋)的最好方法是在表达式上使用ToString()并比较它们。

Expression<Func<bool>> f1 = () => true;
Expression<Func<bool>> f2 = () => true;
Console.WriteLine(f1.ToString());        // Outputs "() => True"
Console.WriteLine("a1 == a2 results in " + (f1.ToString() == f2.ToString()));  // True

您必须小心使用此技术,因为两个表达式“x =&gt; x”和“y =&gt; y”虽然功能相同,但由于参数不同,仍会评估为false。还要注意,必须使用Expression而不是Func或Action才能使用此ToString()技巧。